mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 14:25:26 +00:00
lib/cmap: cmap_find_batch().
Batching the cmap find improves the memory behavior with large cmaps and can make searches twice as fast: $ tests/ovstest test-cmap benchmark 2000000 8 0.1 16 Benchmarking with n=2000000, 8 threads, 0.10% mutations, batch size 16: cmap insert: 533 ms cmap iterate: 57 ms batch search: 146 ms cmap destroy: 233 ms cmap insert: 552 ms cmap iterate: 56 ms cmap search: 299 ms cmap destroy: 229 ms hmap insert: 222 ms hmap iterate: 198 ms hmap search: 2061 ms hmap destroy: 209 ms Batch size 1 has small performance penalty, but all other batch sizes are faster than non-batched cmap_find(). The batch size 16 was experimentally found better than 8 or 32, so now classifier_lookup_miniflow_batch() performs the cmap find operations in batches of 16. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
34
lib/cmap.h
34
lib/cmap.h
@@ -106,6 +106,14 @@ size_t cmap_replace(struct cmap *, struct cmap_node *old_node,
|
||||
* Thread-safety
|
||||
* =============
|
||||
*
|
||||
* CMAP_NODE_FOR_EACH will reliably visit each of the nodes starting with
|
||||
* CMAP_NODE, even with concurrent insertions and deletions. (Of
|
||||
* course, if nodes are being inserted or deleted, it might or might not visit
|
||||
* the nodes actually being inserted or deleted.)
|
||||
*
|
||||
* CMAP_NODE_FOR_EACH_PROTECTED may only be used if the containing CMAP is
|
||||
* guaranteed not to change during iteration. It may be only slightly faster.
|
||||
*
|
||||
* CMAP_FOR_EACH_WITH_HASH will reliably visit each of the nodes with the
|
||||
* specified hash in CMAP, even with concurrent insertions and deletions. (Of
|
||||
* course, if nodes with the given HASH are being inserted or deleted, it might
|
||||
@@ -114,19 +122,35 @@ size_t cmap_replace(struct cmap *, struct cmap_node *old_node,
|
||||
* CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not
|
||||
* to change during iteration. It may be very slightly faster.
|
||||
*/
|
||||
#define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP) \
|
||||
for (INIT_CONTAINER(NODE, cmap_find(CMAP, HASH), MEMBER); \
|
||||
(NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
|
||||
#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE) \
|
||||
for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER); \
|
||||
(NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
|
||||
ASSIGN_CONTAINER(NODE, cmap_node_next(&(NODE)->MEMBER), MEMBER))
|
||||
#define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP) \
|
||||
for (INIT_CONTAINER(NODE, cmap_find_locked(CMAP, HASH), MEMBER); \
|
||||
#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE) \
|
||||
for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER); \
|
||||
(NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER); \
|
||||
ASSIGN_CONTAINER(NODE, cmap_node_next_protected(&(NODE)->MEMBER), \
|
||||
MEMBER))
|
||||
#define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP) \
|
||||
CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH))
|
||||
#define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP) \
|
||||
CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, cmap_find_locked(CMAP, HASH))
|
||||
|
||||
const struct cmap_node *cmap_find(const struct cmap *, uint32_t hash);
|
||||
struct cmap_node *cmap_find_protected(const struct cmap *, uint32_t hash);
|
||||
|
||||
/* Looks up multiple 'hashes', when the corresponding bit in 'map' is 1,
|
||||
* and sets the corresponding pointer in 'nodes', if the hash value was
|
||||
* found from the 'cmap'. In other cases the 'nodes' values are not changed,
|
||||
* i.e., no NULL pointers are stored there.
|
||||
* Returns a map where a bit is set to 1 if the corresponding 'nodes' pointer
|
||||
* was stored, 0 otherwise.
|
||||
* Generally, the caller wants to use CMAP_NODE_FOR_EACH to verify for
|
||||
* hash collisions. */
|
||||
unsigned long cmap_find_batch(const struct cmap *cmap, unsigned long map,
|
||||
uint32_t hashes[],
|
||||
const struct cmap_node *nodes[]);
|
||||
|
||||
/* Iteration.
|
||||
*
|
||||
*
|
||||
|
Reference in New Issue
Block a user