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

hashbrown: the standard library already ships this hash table, and its default hasher gives up hash flooding resistance

Rust port of Google's SwissTable hash map

3,013 stars365 forksRustApache-2.0

At a glance

What is it?
A Rust port of Google's SwissTable hash map that the standard library adopted years ago, still worth using where the standard library is not available and worth reading carefully before you expose it, because the faster default hasher it now ships is documented as offering less resistance to hash denial of service than the one it replaced.
Who is it for?
hashbrown fits a no_std target, a kernel, an allocator with its own interface, or a codebase that wants the extra memory and lookup characteristics on a standard target. It does not fit anyone who needs a hash map with flood resistance out of the box.
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 1 day 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 November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • rust-lang/hashbrown3,013 ★ · +15
Star history
Repository2026-09-242026-11-14
rust-lang/hashbrown3k3k

15 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The standard library already contains this hash table

The second paragraph of the README is the one that changes how you read the rest of it. Since a Rust version in the 1.36 series, the standard library has adopted this implementation for its own map and set types, using its own default hasher. So the crate is no longer a faster map: it is the same algorithm, and the performance claims in the feature list are stated against the previous standard library implementation, not against the current one. The README then says why you might still want the crate anyway, and the reason is narrow and specific: it works in environments without the standard library, such as embedded systems and kernels. That reframes the whole project. It is not a faster map for server code, it is the standard library's map made available where the standard library is not, plus the extras the standard library does not turn on.

The default hasher gives up hash flooding resistance, and the README says so

One feature bullet is a security note wearing a performance hat. The default hasher is a fast hash function the README describes as much faster than the one the standard library uses, and then states in the same bullet that it does not provide the same level of hash denial of service resistance, suggesting you use a different hasher if that matters to you. That sentence should decide the default for a lot of projects. Hash flooding resistance is what stops an attacker who controls map keys from choosing keys that all land in the same bucket and turning a lookup into a linear scan. The faster function makes the honest case for itself on throughput and gives that property up, and the documentation is unusually direct about the trade rather than burying it. The feature that controls this is on by default, so the default build is the fast, less resistant configuration.

Two dependencies alias compiler internal crate names

Two lines in the dependency table are unlike anything else in the manifest. One declares a dependency on the package named core but pointing at a different package, an internal workspace crate from the compiler, and does the same for a package named alloc. Both are optional, and the comment above them says when they are used: when this crate is built as part of the standard library. That constraint explains a lot about the code. A crate that has to compile inside the compiler's own build cannot use anything the standard library does not already provide, which is why the no_std story is a first class concern here rather than an afterthought, and why the dependency on an allocator is part of the contract. It also means the published crate carries two optional dependencies that are not available from the public registry at all, and resolving them requires a toolchain build rather than a package index.

Four of nine features are on by default, one of them deprecated

The feature list has nine entries and four are marked as enabled by default. The interesting ones are not all about speed. One default feature enables a custom comparison trait, so callers can decide what equality means for their keys. Another compiles in the fast default hasher, which is the switch behind the previous section's trade. A third adds support for allocators that use a newer allocator interface. The fourth adds inline hints to most functions, which the README describes as improving runtime performance at the cost of compilation time, which is a trade almost nobody makes by accident. And one non-default feature exists purely to keep the old raw entry API reachable even though the README labels it deprecated, so code written against the previous interface can still be migrated gradually rather than all at once.

The manifest asks you to sync the minimum Rust version by hand

One comment in the package section is a maintenance instruction aimed at contributors rather than users. It sits directly above the declared minimum supported Rust version and says to make sure that version is synchronised in the README badge and in the continuous integration workflows. In other words the crate has three places that must agree about which compiler versions it supports, and nothing enforces the agreement. The visible badge row does not include a version badge at all, so of the three locations the one a reader would consult is the one that is missing. The manifest also declares an edition, turns off automatic benchmark discovery, and excludes a workflow directory and a continuous integration directory from the published package, which is consistent with a crate that cares about what ships.

A long list of pedantic lints, including one against a specific conversion

The lint configuration is longer than most of the manifest and says more about how the project is worked on than the feature list does. The Rust lints require documentation on missing items, warn on unreachable public items, and warn on unsafe operations inside unsafe functions, which is the modern form of a rule that used to be an opt in attribute. Underneath them sits a commented out line for a group of idioms, meaning the author considered enabling them and decided not to. The clippy section is split in two. Seven lints are allowed outright, including documentation formatting, manual map construction, missing error and safety documentation, and a candidate lint that would require marking every fallible function. Then twenty are set to warn, and they are the pedantic ones: manual assertions in both forms, manual let-else, needless continue, redundant else, pointer casts in several shapes, a semicolon check on empty function bodies, and one that warns against converting a string slice into an owned string. That last group is a style constitution, written as lints so it cannot be forgotten in review.

One byte of overhead per entry, and no allocation until something is inserted

The performance claims are concrete enough to check. The usage section is the shortest thing in the README: add the dependency to your manifest, then create a map and insert a key. The manifest line is:

toml
[dependencies]
hashbrown = "0.17"

Memory overhead is stated as one byte per entry against eight for the previous standard library implementation, which is a large ratio for a data structure that is mostly the keys and values themselves. Empty maps are stated not to allocate at all, which means a map declared as a field or held in a struct costs nothing until first use. Lookups are described as using SIMD to scan multiple hash entries in parallel, which is the part that distinguishes this design from the open addressing schemes that scan one control byte at a time. Speed is claimed at roughly twice the previous standard library map. Each of these is a claim about a specific comparison point that no longer exists in the current standard library, so the honest reading is that they document why the design is good rather than what you will measure today. The cross-compilation configuration and the continuous integration directory are where you would go to reproduce any of it.

Editorial conclusion

hashbrown fits a no_std target, a kernel, an allocator with its own interface, or a codebase that wants the extra memory and lookup characteristics on a standard target. It does not fit anyone who needs a hash map with flood resistance out of the box. Three things to know. Since the standard library adopted the same algorithm, the reason to take the crate directly is no_std, an allocator with a custom interface, or a specific feature; the performance claims are relative to an older standard library version. The default hasher is explicitly documented as offering less hash denial of service resistance than the one it replaced, so choose a hasher deliberately if keys can be attacker controlled. And the manifest carries two dependencies that alias compiler internal crate names so this crate can also be built inside the standard library, which constrains what the code may use.

Frequently asked questions

What is hashbrown?

A Rust port of Google's SwissTable hash map, adapted to be a drop-in replacement for the standard library's HashMap and HashSet. The standard library adopted the same implementation in Rust 1.36 with its own default hasher, so the crate is still worth using where the standard library is not available, such as embedded systems and kernels.

Is hashbrown's default hasher resistant to hash flooding?

No, and the README says so. The default hasher is described as much faster than the one the standard library uses, but it does not provide the same level of hash denial of service resistance, and the README suggests using a different hasher if that matters. The feature enabling it is on by default.

What Cargo features does hashbrown have?

Nine: a nightly feature for unstable items, serde serialization, rayon parallel iterators, custom comparisons through a trait enabled by default, access to the deprecated raw entry API, inline hints that trade compile time for runtime speed and are on by default, compiling in the default hasher, and support for a newer allocator interface, also on by default.

How much memory does hashbrown save compared with the standard map?

The README claims one byte of overhead per entry instead of eight, around twice the speed of the previous standard library map, that empty maps do not allocate at all, and that lookups use SIMD to scan several hash entries in parallel. Those comparisons are against a standard library version that has since adopted the same algorithm.

Can hashbrown be used without the standard library?

Yes. It is compatible with no_std provided a global allocator supplied by the alloc crate is available, and that is the main reason to take the crate directly even though the standard library now contains the same hash table implementation.

Why does hashbrown depend on internal compiler crates?

Two optional dependencies declare package names that alias internal workspace crates for core and alloc, and the comment above them says they apply when the crate is built as part of the standard library. Those two are not resolvable from a public package index, so the constraint shapes what the crate may use and how it is built.

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)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/rust-lang-hashbrown.svg)](https://hysenlabs.com/projects/rust-lang-hashbrown)

Was this useful?