Hash-based dedup in BoxScanner instead of std::set<pair>#2377
Hash-based dedup in BoxScanner instead of std::set<pair>#2377nikosavola wants to merge 1 commit into
std::set<pair>#2377Conversation
|
Hi @nikosavola, thanks for the patch. The reason I used the pairs was - as far as I recall - memory concerns. When you use a map of sets you allocate two pointers for a "lonely" pair, while you allocate a pointer plus memory for a set in the other case. With hash maps there always is a bigger overhead due to capacity pre-allocation, so I wonder what the memory effects are. Do you have some numbers from your benchmarks? Another thing about unordered sets and maps - specifically pointers - is reproducibility of the order, but I don't think that counts here. Thanks, Matthias |
You're right, the lonely pairs will be more expensive. Here's a table of the peak seen memory usage for various workloads, with the
The high-overlap cases this PR should accelerate use ~40% less memory, while the worst case lonely pairs end up with 4.29× more memory usage. I think the memory overhead for the typical low overlap cases is also minimal in the end. |
Before a
std::set<std::pair<Obj*, Obj*>>was holding every reported pair. In this PR, we change it to a hash table keyed on one pointer, whose value is a hash set of the partners.This makes the membership tests for candidate pairs a hash map check. Removal also becomes a simple
seen.erase(X).Results
Best of 9 runs, single core (
taskset -c 0),g++ 14.2 -O2 -std=c++17, glibc 2.41. Time is the fullprocess()call (ms):The win scales with how large the
seenset grows: light/sparse inputs (the common case) are neutral-to-slightly-better, while high-overlap inputs walked the tree more.Reproduce