martinus / unordered_dense

A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion
MIT License
898 stars 72 forks source link

implement a version with stable iterators #38

Closed martinus closed 1 year ago

martinus commented 2 years ago

robin_hood map has an option for stable iterators, that's currently not possible with unordered_dense.

One way to implement this might be be to be able to replace the underlying container with some kind of slotmap.

Slot map design

Insert: O(1) amortized.

Take the index after size, construct element in that location in data. Increase size by 1. When capacity is reached we know data is completely full. push back a new index with size and construct there.

Erase at location x: O(1)

  1. Lookup in index[x] and destroy that element.
  2. std::swap(index[x], index.back())
  3. decrease size by one. Now we have one more entry in our free section (past the size)

Iterate

Needs a custom iterator that goes over the index and dereferences from there.

Open questions

Philippe91 commented 2 years ago

To further dismiss the std::deque option: the performance is very dependent on the stl implementation (and probably the underlying chunk size). I found that with MSVC, the performance is surprisingly bad.

martinus commented 2 years ago

More thoughts:

Philippe91 commented 2 years ago

Yes, I made a similar container, precisely because std::deque was found to be slow. My primary interest was to prevent reallocation, in the context of acquiring random batches of data in real-time.

Philippe91 commented 1 year ago

This is not too clear from your doc, but with segmented_map, we get stable buckets; that is, once inserted in the map, a key/value pair will never be moved, whatever mutation happens to the map (right?). In which case do we not have iterator stability, given this fact?

martinus commented 1 year ago

With segmented_map you'll get stable iterators & references on insert, but not on erase.

Philippe91 commented 1 year ago

Thank you for your answer; it would be worth clarifying this in your documentation about segment_map.

martinus commented 1 year ago

Closing the issue as I won't have time to work on this