#hash-table #hash-map #hash-values #no-std

no-std ordermap

A hash table with consistent order and fast iteration

30 releases

0.5.4 Dec 1, 2024
0.5.3 Aug 30, 2024
0.5.0 Jun 25, 2024
0.4.2 Nov 17, 2018
0.2.7 Nov 2, 2016

#30 in #hashmap

Download history 10515/week @ 2024-08-30 9324/week @ 2024-09-06 7817/week @ 2024-09-13 12080/week @ 2024-09-20 12335/week @ 2024-09-27 14500/week @ 2024-10-04 13963/week @ 2024-10-11 12416/week @ 2024-10-18 11665/week @ 2024-10-25 12374/week @ 2024-11-01 8459/week @ 2024-11-08 12937/week @ 2024-11-15 13345/week @ 2024-11-22 15793/week @ 2024-11-29 12942/week @ 2024-12-06 12302/week @ 2024-12-13

58,046 downloads per month
Used in fewer than 14 crates

Apache-2.0 OR MIT

235KB
4K SLoC

ordermap

build status crates.io docs rustc

A pure-Rust hash table which preserves (in a limited sense) insertion order.

This crate implements compact map and set data-structures, where the iteration order of the keys is independent from their hash or value. It preserves insertion order in most mutating operations, and it allows lookup of entries by either hash table key or numerical index.

Note: this crate was originally what became the indexmap crate, and it was deprecated for a while in favor of that, but then ordermap returned as a wrapper over indexmap with stronger ordering properties.

Background

This was inspired by Python 3.6's new dict implementation (which remembers the insertion order and is fast to iterate, and is compact in memory).

Some of those features were translated to Rust, and some were not. The results were ordermap and indexmap, hash tables that have following properties:

  • Order is independent of hash function and hash values of keys.
  • Fast to iterate.
  • Indexed in compact space.
  • Preserves insertion order as long as you don't call .swap_remove() or other methods that explicitly change order.
    • In ordermap, the regular .remove() does preserve insertion order, equivalent to what indexmap calls .shift_remove().
  • Uses hashbrown for the inner table, just like Rust's libstd HashMap does.

Since its reintroduction in 0.5, ordermap has also used its entry order for PartialEq and Eq, whereas indexmap considers the same entries in any order to be equal for drop-in compatibility with HashMap semantics. Using the order is faster, and also allows ordermap to implement PartialOrd, Ord, and Hash.

Performance

OrderMap derives a couple of performance facts directly from how it is constructed, which is roughly:

A raw hash table of key-value indices, and a vector of key-value pairs.

  • As a wrapper, OrderMap should maintain the same performance as IndexMap for most operations, with the main difference being the removal strategy.
  • Iteration is very fast since it is on the dense key-values.
  • Lookup is fast-ish because the initial 7-bit hash lookup uses SIMD, and indices are densely stored. Lookup also is slow-ish since the actual key-value pairs are stored separately. (Visible when cpu caches size is limiting.)
  • In practice, OrderMap has been tested out as the hashmap in rustc in PR45282 and the performance was roughly on par across the whole workload.
  • If you want the properties of OrderMap, or its strongest performance points fits your workload, it might be the best hash table implementation.

Recent Changes

See RELEASES.md.

Dependencies

~0.7–1.6MB
~28K SLoC