Library / SDK
rust-lang/hashbrown avatar
rust-lang/hashbrown

hashbrown: Rust's SwissTable HashMap Outside the Standard Library

Rust port of Google's SwissTable hash map

2,997 stars359 forksRustApache-2.0

At a glance

What is it?
hashbrown is the Rust port of Google's SwissTable that the standard library already uses for HashMap, packaged as a crate so no_std targets can have it too. The trade-off is its default hasher, which is fast but not HashDoS resistant.
Who is it for?
Adopt hashbrown when you need HashMap or HashSet in a no_std crate with an allocator, or when you want a hasher faster than SipHash and have judged the HashDoS trade-off acceptable. Do not adopt it merely because it is faster than std: since Rust 1.36 the standard library uses this same SwissTable implementation, so a std binary gains little beyond the hasher swap.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What hashbrown Solves, and Who Actually Needs It

hashbrown is a Rust port of Google's SwissTable hash map, adapted to be a drop-in replacement for the standard library's HashMap and HashSet types. The README is explicit about the awkward position this creates: since Rust 1.36 the standard library has adopted this implementation for HashMap, using its own default hasher. So on a normal std binary, you already have the data structure. The crate's own justification for existing is narrower than its reputation suggests. It works in environments without std, such as embedded systems and kernels. That is the audience: firmware, kernels, and any crate compiled with #[no_std] that still has access to a global allocator through the alloc crate. The README notes that empty hash maps do not allocate any memory, which matters when a map is a field in a struct that may never be populated. If you are writing an application that links std and you are not fighting allocation behaviour, the case for adding this dependency is mostly about the default hasher, and that is a decision with a security dimension covered below.

How SwissTable Works Inside hashbrown

The mechanism is the part worth understanding before you swap it in. SwissTable stores entries in groups and keeps a separate array of one-byte control values alongside the slots. Each control byte encodes the top seven bits of the hash of the entry in that slot, with reserved values marking empty and deleted slots. A lookup computes the hash once, takes the matching control byte, and compares it against the control bytes of an entire group at once. The README describes this as SIMD lookups to scan multiple hash entries in parallel, which is why the control array exists as a separate structure rather than as metadata interleaved with the keys and values. The memory claim follows from the same design: the README states the map uses only 1 byte of overhead per entry instead of 8. That is the control byte. A conventional open-addressing table that stores a full hash or a state word per slot pays more per entry, and the gap widens on small keys and values where metadata dominates. On the hashing side, hashbrown uses foldhash as the default hasher, described in the README as much faster than SipHash. The README also states the crate is around 2x faster than the previous standard library HashMap, a claim that refers to the pre-SwissTable implementation, not to the current std. Read that number as a historical comparison, not as an advantage over today's standard library.

Installing hashbrown and Using It in a no_std Crate

The README gives the dependency line directly. The crate version in the current Cargo.toml is 0.17.1, and the README's usage example pins the minor version. Add this to your manifest:

toml
[dependencies]
hashbrown = "0.17"

The README then shows the minimal program, which is identical in shape to std usage. The use statement is the only thing that changes:

rust
use hashbrown::HashMap;

let mut map = HashMap::new();
map.insert(1, "one");

In a no_std crate the surrounding setup differs, because the crate requires a global allocator through the alloc crate. The README states this requirement plainly but does not print a full no_std example, so the exact allocator wiring is something you supply for your target. Cargo.toml declares edition = "2024" and rust-version = "1.85.0", with a comment telling maintainers to keep that minimum in sync with the README badge and CI workflows. Confirm your toolchain before you start. The crate exposes Cargo features that change what you get: serde for serialization support, rayon for parallel iterator support, nightly for nightly-only features including #[may_dangle], and raw-entry for the deprecated RawEntry API. Several are on by default, including equivalent, inline-more, default-hasher and allocator-api2. Turning off default-hasher removes foldhash and forces you to supply a hasher, which is the configuration to consider if the default does not suit you.

The foldhash Default Is the Real Adoption Decision

This is where hashbrown differs from std in a way that has consequences. The README states that foldhash does not provide the same level of HashDoS resistance as SipHash, and follows it with a direct instruction: if that is important to you, you might want to consider using a different hasher. That is an unusually blunt note in a crate README, and it should be read as the maintainers telling you the default is chosen for speed. HashDoS is a denial-of-service attack in which an adversary who can influence the keys inserted into a map engineers collisions, degrading lookups toward linear scans. If your keys come from untrusted input over a network, and an attacker can choose them, the default hasher is the wrong choice and you should configure a different one. If your keys are integers, internal identifiers, or anything an outside party cannot steer, the speed is free. Note that this is a property of the default, not of the table. The control-byte design is orthogonal to hashing quality; a weak hasher degrades any open-addressing table the same way. The feature flag default-hasher exists precisely so you can opt out of foldhash without abandoning the crate. The README does not name which hasher to use instead, so choosing a HashDoS-resistant replacement is left to you.

When hashbrown Is the Wrong Dependency

The clearest case against it is a std application that already works. The README says the standard library adopted this implementation in Rust 1.36, so the structural advantage is gone; what remains is the default hasher and the feature set. If you are not in no_std and you do not need serde, rayon, or the allocator-api2 integration, adding hashbrown is a dependency you may not need. The second case is a no_std target without a global allocator. The README is explicit that no_std compatibility requires a global allocator with the alloc crate. On a microcontroller where you have deliberately avoided a heap, hashbrown is not a substitute for a fixed-capacity map, and no feature flag changes that. The third case is a threat model that includes adversarial keys. As covered above, the default hasher trades HashDoS resistance for speed, and the README says so. There is also a maintenance dimension worth weighing. The last push to the default branch was on 2026-09-06, which is recent, and the most recent release listed is v0.17.1 from 2026-05-09. The crate is not archived. That said, the lints block in Cargo.toml sets missing_docs and unreachable_pub to warn rather than deny, and clippy.toml sits at the repository root, so the project's own standards are visible in the tree. Nothing in the repository documents a rollback or downgrade procedure, and the README does not discuss what happens to serialized data when the format changes between versions.

hashbrown Against a Plain BTreeMap or a Custom Hasher

The alternative depends on what you are actually missing. If your problem is that std HashMap is unavailable because you are in no_std, the realistic comparison is not another hash table but alloc::collections::BTreeMap, which is ordered and also requires the alloc crate. BTreeMap gives you sorted iteration and range queries for free, and it has no hasher to configure, which removes the foldhash decision entirely. The cost is that lookups are O(log n) with pointer-chasing through nodes rather than the amortised O(1) of an open-addressing table with SIMD group scanning. If your workload is lookup-heavy and your keys hash well, hashbrown's design is the better fit; if you iterate in key order more often than you look up, BTreeMap may be simpler. If your problem is the hasher rather than the table, the alternative is not a different crate but a different configuration: disable the default-hasher feature and supply your own. That keeps the SwissTable layout, the 1-byte-per-entry control array, and the SIMD probing, while removing foldhash from the picture. The README does not name a recommended replacement hasher, so that choice is yours to make and to justify.

Licence and Upgrade Cost

hashbrown is dual licensed under Apache-2.0 and MIT, at your option. Both licence files sit at the repository root as LICENSE-APACHE and LICENSE-MIT, and Cargo.toml declares license = "MIT OR Apache-2.0". The README adds the standard contribution clause: unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. For most users this is the least complicated part of adoption; the dual grant is permissive and matches what much of the Rust ecosystem already uses. This is a description of what the files say, not legal advice, and if your organisation has specific policy about dual-licensed dependencies you should route it through whoever handles that. On upgrade cost, the version history shows v0.16.1, then v0.17.0, then v0.17.1, with the two 0.17 releases about a month apart. The README's usage example pins "0.17", so a Cargo.lock will hold you within that minor line. The feature list is the thing to re-read on each upgrade, because defaults can shift: equivalent, inline-more, default-hasher and allocator-api2 are all enabled by default in this version, and the hasher default is the one with security implications if it ever changes.

Editorial conclusion

Adopt hashbrown when you need HashMap or HashSet in a no_std crate with an allocator, or when you want a hasher faster than SipHash and have judged the HashDoS trade-off acceptable. Do not adopt it merely because it is faster than std: since Rust 1.36 the standard library uses this same SwissTable implementation, so a std binary gains little beyond the hasher swap. Before committing, verify that your target provides a global allocator through the alloc crate, check that the foldhash default matches your threat model, and confirm your toolchain meets the rust-version = "1.85.0" floor declared in Cargo.toml.

Frequently asked questions

What is hashbrown in Rust?

It is a Rust port of Google's high-performance SwissTable hash map, adapted as a drop-in replacement for the standard library HashMap and HashSet types. The README notes that since Rust 1.36 the standard library has used this implementation, so the crate's main draw is working in environments without std.

How do I install hashbrown?

Add hashbrown = "0.17" to the dependencies section of your Cargo.toml, then import with use hashbrown::HashMap. The README shows exactly this pair of steps.

Does hashbrown work without std?

Yes. The README states it is compatible with #[no_std], but requires a global allocator with the alloc crate. Without an allocator it is not a usable replacement for a fixed-capacity map.

Is hashbrown's default hasher safe against HashDoS?

The README states that foldhash, the default hasher, does not provide the same level of HashDoS resistance as SipHash, and suggests considering a different hasher if that matters to you. The default-hasher feature flag controls whether foldhash is compiled in.

What is the minimum supported Rust version for hashbrown?

Cargo.toml declares rust-version = "1.85.0" and edition = "2024", with a comment instructing maintainers to keep that minimum in sync with the README badge and CI workflows.

Which licence does hashbrown use?

It is dual licensed under Apache-2.0 and MIT, at your option, with LICENSE-APACHE and LICENSE-MIT at the repository root and license = "MIT OR Apache-2.0" in Cargo.toml.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. rust-lang/hashbrown on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rust-lang-hashbrown.svg)](https://hysenlabs.com/projects/rust-lang-hashbrown)