summaryrefslogtreecommitdiff
path: root/lib/cmap.h
Commit message (Collapse)AuthorAgeFilesLines
* cmap: use multi-variable iterators.Adrian Moreno2022-03-301-10/+12
| | | | | | | | | | | | Re-write cmap's loops using multi-variable helpers. For iterators based on cmap_cursor, we just need to make sure the NODE variable is not used after the loop, so we set it to NULL. Acked-by: Eelco Chaudron <echaudro@redhat.com> Acked-by: Dumitru Ceara <dceara@redhat.com> Signed-off-by: Adrian Moreno <amorenoz@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
* util: Add token concatenation macro with argument expansion.Paolo Valerio2021-07-081-4/+1
| | | | | | | | | | | | | This macro is handy when it comes paste two tokens when one or both are macros. Rename CURSOR_JOIN() to OVS_JOIN() and move it to util.h so that it can be reused. Signed-off-by: Paolo Valerio <pvalerio@redhat.com> Acked-by: Gaetan Rivet <grive@u256.net> Acked-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
* dpif-netdev: Add SMC cache after EMC cacheYipeng Wang2018-07-241-0/+11
| | | | | | | | | | | | | | | | | | | | | | This patch adds a signature match cache (SMC) after exact match cache (EMC). The difference between SMC and EMC is SMC only stores a signature of a flow thus it is much more memory efficient. With same memory space, EMC can store 8k flows while SMC can store 1M flows. It is generally beneficial to turn on SMC but turn off EMC when traffic flow count is much larger than EMC size. SMC cache will map a signature to an dp_netdev_flow index in flow_table. Thus, we add two new APIs in cmap for lookup key by index and lookup index by key. For now, SMC is an experimental feature that it is turned off by default. One can turn it on using ovsdb options. Signed-off-by: Yipeng Wang <yipeng1.wang@intel.com> Co-authored-by: Jan Scheurich <jan.scheurich@ericsson.com> Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com> Acked-by: Billy O'Mahony <billy.o.mahony@intel.com> Signed-off-by: Ian Stokes <ian.stokes@intel.com>
* cmap: Allow CMAP_FOR_EACH to be nested without shadowing variables.Justin Pettit2018-02-281-3/+12
| | | | | Signed-off-by: Justin Pettit <jpettit@ovn.org> Acked-by: Ben Pfaff <blp@ovn.org>
* cmap: Fix example provided for CMAP_FOR_EACH.Justin Pettit2018-02-281-4/+3
| | | | | Signed-off-by: Justin Pettit <jpettit@ovn.org> Acked-by: Ben Pfaff <blp@ovn.org>
* cmap: Fix bug in CMAP_FOR_EACH_WITH_HASH_PROTECTED.zhangliping2018-02-261-1/+1
| | | | | | | | | | | cmap_find_locked() should be cmap_find_protected(). This does not fix a user-visible bug because this macro did not have any users. Signed-off-by: zhangliping <zhangliping02@baidu.com> Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Mark Michelson <mmichels@redhat.com>
* cmap: New macro CMAP_INITIALIZER, for initializing an empty cmap.Ben Pfaff2016-05-091-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | Sometimes code is much simpler if we can statically initialize data structures. Until now, this has not been possible for cmap-based data structures, so this commit introduces a CMAP_INITIALIZER macro. This works by adding a singleton empty cmap_impl that simply forces the first insertion into any cmap that points to it to allocate a real cmap_impl. There could be some risk that rogue code modifies the singleton, so for safety it is also marked 'const' to allow the linker to put it into a read-only page. This adds a new OVS_ALIGNED_VAR macro with GCC and MSVC implementations. The latter is based on Microsoft webpages, so developers who know Windows might want to scrutinize it. As examples of the kind of simplification this can make possible, this commit removes an initialization function from ofproto-dpif-rid.c and a call to cmap_init() from tnl-neigh-cache.c. An upcoming commit will add another user. CC: Jarno Rajahalme <jarno@ovn.org> CC: Gurucharan Shetty <guru@ovn.org> Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Ryan Moats <rmoats@us.ibm.com>
* cmap: Explain corner case in CMAP_FOR_EACH comment.Daniele Di Proietto2016-02-031-0/+5
| | | | | | | | | Commit d916785ce98c("dpif-netdev: Fix improper use of CMAP_FOR_EACH.") fixes a problem that's worth documenting. Requested-by: Jarno Rajahalme <jarno@ovn.org> Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com> Acked-by: Ben Pfaff <blp@ovn.org>
* lib/cmap: cmap_find_batch().Jarno Rajahalme2014-10-061-5/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* lib/cmap: split up cmap_find().Jarno Rajahalme2014-10-061-1/+1
| | | | | | | | | This makes the following patch easier and cleans up the code. Explicit "inline" keywords seem necessary to prevent performance regression on cmap_find() with GCC 4.7 -O2. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
* lib/cmap: Return number of nodes from functions modifying the cmap.Jarno Rajahalme2014-10-061-5/+21
| | | | | | | | | We already update the count field as the last step of these functions, so returning the current count is very cheap. Callers that care about the count become a bit more efficient, as they avoid extra non-inlineable function call. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
* Avoid uninitialized variable warnings with OBJECT_OFFSETOF() in MSVC.Gurucharan Shetty2014-09-121-3/+3
| | | | | | | | | | | | | | Implementation of OBJECT_OFFSETOF() for non-GNUC compilers like MSVC causes "uninitialized variable" warnings. Since OBJECT_OFFSETOF() is indirectly used through all the *_FOR_EACH() (through ASSIGN_CONTAINER() and OBJECT_CONTAINING()) macros, the OVS build on Windows gets littered with "uninitialized variable" warnings. This patch attempts to workaround the problem. Signed-off-by: Gurucharan Shetty <gshetty@nicira.com> Acked-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com> Acked-by: Saurabh Shah <ssaurabh@vmware.com> Acked-by: Ben Pfaff <blp@nicira.com>
* cmap: Merge CMAP_FOR_EACH_SAFE into CMAP_FOR_EACH.Ben Pfaff2014-07-291-36/+21
| | | | | | | | | | There isn't any significant downside to making cmap iteration "safe" all the time, so this drops the _SAFE variant. Similar changes to CMAP_CURSOR_FOR_EACH and CMAP_CURSOR_FOR_EACH_CONTINUE. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
* cmap, classifier: Avoid unsafe aliasing in iterators.Ben Pfaff2014-07-211-54/+38
| | | | | | | | | | | | | | | | CMAP_FOR_EACH and CLS_FOR_EACH and their variants tried to use void ** as a "pointer to any kind of pointer". That is a violation of the aliasing rules in ISO C which technically yields undefined behavior. With GCC 4.1, it causes both warnings and actual misbehavior. One option would to add -fno-strict-aliasing to the compiler flags, but that would only help with GCC; who knows whether this can be worked around with other compilers. Instead, this commit rewrites the iterators to avoid disallowed pointer aliasing. VMware-BZ: #1287651 Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
* lib/cmap: Simplify iteration with C99 loop declaration.Jarno Rajahalme2014-06-111-5/+38
| | | | | | | | | | This further eases porting existing hmap code to use cmap instead. The iterator variants taking an explicit cursor are retained (renamed) as they are needed when iteration is to be continued from the last iterated node. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
* lib/cmap: Add more hmap-like functionality.Jarno Rajahalme2014-05-281-8/+38
| | | | | | | | | | | | Add cmap_replace() and cmap_first(), as well as CMAP_FOR_EACH_SAFE and CMAP_FOR_EACH_CONTINUE to make porting existing hmap using code a bit easier. CMAP_FOR_EACH_SAFE is useful in RCU postponed destructors, when it is known that additional postponing is not needed. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
* cmap: New module for cuckoo hash table.Ben Pfaff2014-05-201-0/+196
This implements an "optimistic concurrent cuckoo hash", a single-writer, multiple-reader hash table data structure. The point of this data structure is performance, so this commit message focuses on performance. I tested the performance of cmap with the test-cmap utility included in this commit. It takes three parameters for benchmarking: - n, the number of elements to insert. - n_threads, the number of threads to use for searching and mutating the hash table. - mutations, the percentage of operations that should modify the hash table, from 0% to 100%. e.g. "test-cmap 1000000 16 1" inserts one million elements, uses 16 threads, and 1% of the operations modify the hash table. Any given run does the following for both hmap and cmap implementations: - Inserts n elements into a hash table. - Iterates over all of the elements. - Spawns n_threads threads, each of which searches for each of the elements in the hash table, once, and removes the specified percentage of them. - Removes each of the (remaining) elements and destroys the hash table. and reports the time taken by each step, The tables below report results for various parameters with a draft version of this library. The tests were not formally rerun for the final version, but the intermediate changes should only have improved performance, and this seemed to be the case in some informal testing. n_threads=16 was used each time, on a 16-core x86-64 machine. The compiler used was Clang 3.5. (GCC yields different numbers but similar relative results.) The results show: - Insertion is generally 3x to 5x faster in an hmap. - Iteration is generally about 3x faster in a cmap. - Search and mutation is 4x faster with .1% mutations and the advantage grows as the fraction of mutations grows. This is because a cmap does not require locking for read operations, even in the presence of a writer. With no mutations, however, no locking is required in the hmap case, and the hmap is somewhat faster. This is because raw hmap search is somewhat simpler and faster than raw cmap search. - Destruction is faster, usually by less than 2x, in an hmap. n=10,000,000: .1% mutations 1% mutations 10% mutations no mutations cmap hmap cmap hmap cmap hmap cmap hmap insert: 6132 2182 6136 2178 6111 2174 6124 2180 iterate: 370 1203 378 1201 370 1200 371 1202 search: 1375 8692 2393 28197 18402 80379 1281 1097 destroy: 1382 1187 1197 1034 324 241 1405 1205 n=1,000,000: .1% mutations 1% mutations 10% mutations no mutations cmap hmap cmap hmap cmap hmap cmap hmap insert: 311 25 310 60 311 59 310 60 iterate: 25 62 25 64 25 57 25 60 search: 115 637 197 2266 1803 7284 101 67 destroy: 103 64 90 59 25 13 104 66 n=100,000: .1% mutations 1% mutations 10% mutations no mutations cmap hmap cmap hmap cmap hmap cmap hmap insert: 25 6 26 5 25 5 25 5 iterate: 1 3 1 3 1 3 2 3 search: 12 57 27 219 164 735 10 5 destroy: 5 3 6 3 2 1 6 4 Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>