background: rust defaults to a hashing algorithm that is resistant to collision attacks. This comes at two notable out-of-the-box costs: HashMaps behave non-deterministically and slower.
Long ago we defined https://doc.rust-lang.org/nightly/std/collections/hash_map/struct.DefaultHasher.html which just vaguely promises to have these properties, without guaranteeing any stable algorithm.
While we are adamant on the fact that this is a good default since the issue at hand is obscure and serious, it is definitely not the right solution for everyone. Those who care about determinism or performance and are aware of this situation reach for a custom hasher crate. Notably FxHasher is used by rustc, webrender, and stylo.
I would like to bless this pattern and make it easier to reach for random users who aren’t well-versed in all of the options and the situation. This is done with three steps:
- Define
struct std::collections::hash_map::FastHasher, which opaquely wraps up FxHasher, claims that it is tuned for performance, and guarantees deterministic behaviour for a given input (for a given std version, but the impl may change between versions) (also we still don’t guarantee any particular relationship between iteration and insertion order; that’s what a linked hashmap is for)
- Define
type std::collections::FastHashMap = HashMap<K, V, FastHasher> (yes, at the top!)
- Define
fn HashMap::fast() -> FastHashMap<K, V>
The ideal hasher for your project depends on your keys, but Fx seems to be pretty good for a lot of usecases, and represents a simple win for a lot of crates. Projects which are interested in further tuning may investigate the ecosystem as before.
sfackler suggested breaking this down into subcategories like FastForSmallKeys and FastForBigKeys but I think that’s overkill. I think we want a nice simple story here since the crates.io escape hatch will always exist regardless of what we do.