Open-source project
Nicoshev/rapidhash avatar
Nicoshev/rapidhash

Rapidhash: one hash family in three sizes for C++ callers who care about instruction count

Very fast, high quality, platform-independent hashing algorithm.

914 stars49 forksC++MIT

At a glance

What is it?
Rapidhash is a C++ hash function family offered as rapidhash, rapidhashMicro and rapidhashNano, differing mainly in generated code size and how they behave on large inputs. The MIT licensed header sits in a repository that Chromium, Node, Folly's F14, Fuchsia, Ninja, Julia and zig have all consumed.
Who is it for?
Rapidhash suits C++ developers choosing a general purpose hash for a hash table, cache or build system, and it suits embedded work through rapidhashNano when code size dominates.
Can I use it commercially?
Yes. MIT 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 65 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

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

Editorial analysis

Three functions chosen by how much code you can spend

Rapidhash solves a problem that sounds small until you count instructions. C++ programs hash keys constantly, in hash maps, caches, build logs and network code paths, and each hash function costs code size that has to be fetched, and for smaller targets that is a real constraint. The project answers with a family of three functions rather than one configurable function.

The general purpose entry point is rapidhash, described as having excellent performance across all sizes. rapidhashMicro is aimed at HPC and server use, where cache misses are the thing to avoid, and it compiles to about 140 instructions without stack usage. rapidhashNano targets mobile and embedded code, where keeping the compiled size down matters most, and it compiles to less than 100 instructions, also without stack usage. The general function lands at roughly 185 instructions when compiled with Clang 18 or later.

That framing matters for the choice. If you only ever need one of them, you are not paying for the other two. The trade-off is speed against size, and the crossover points are documented. Micro is faster than the full function for sizes up to 512 bytes, and 15 to 20 percent slower for inputs above 1kb. Nano is the fastest for sizes up to 48 bytes but may be considerably slower for larger inputs.

The catch worth knowing before you pick: Micro produces the same output as rapidhash for inputs up to 80 bytes, and Nano produces the same output as rapidhash for inputs up to 48 bytes. For short keys you can swap the implementation without changing stored hashes, which makes a mixed deployment possible.

A single header that avoids machine specific instruction sets

Based on the repository layout, rapidhash is a header only C++ library. The top level of the tree holds LICENSE, README.md, rapidhash.h, secret.h, and three directories: bench/, collisions/ and old_version/. There is no build system file, no package manifest and no install script in that listing, so adopting the library is a matter of taking the header into your tree rather than linking a library.

The portability story is explicit. The functions are optimized for both AMD64 and AArch64 systems, and the README states that they are compatible with gcc, clang, icx and MSVC. It also states that they do not use machine specific vectorized or cryptographic instruction sets. That last point cuts both ways. It means the same code path runs on any CPU of those two families without needing runtime dispatch, and it means the function is not a cryptographic primitive and does not pretend to be one.

The compiled size claims are also specific about the compiler, since they are stated for Clang 18 and later. A different compiler version or a different optimisation setting will produce a different instruction count, and the project does not publish figures for gcc or MSVC. If code size is the reason you are considering Nano, the honest approach is to compile it with your own toolchain and look at the result rather than to take the number as a promise.

The bench/ and collisions/ directories are worth knowing about for a different reason. They contain the benchmarking program and the collision test program, so the measurements quoted below can be re-run rather than trusted.

Streaming input and the secret that is not a secret

The README lists two properties that matter for how you call the function rather than how fast it runs. The first is that the three functions can be computed without knowing the input length upfront. Most hash APIs want a length argument, which is fine when the buffer is a known array and awkward when the data arrives in pieces. A streamable variant removes that constraint and lets you feed a growing buffer in one pass.

The second property is about seeds. The collision study in the README records that the default seed 0 was used in all experiments, and the repository carries a separate secret.h file next to rapidhash.h. The README does not spell out the contents of secret.h or document the seeding API in prose, so anyone who wants keyed behaviour should read the header directly rather than infer it from the file name.

The honest reading of the default is this. A default seed of 0 is convenient for reproducibility, which is exactly why the published collision numbers are meaningful as a quality measurement, and it also means the default configuration is not a defence against an adversary who knows you are using rapidhash. The README is careful to say the functions use no cryptographic instruction sets, and that is the correct expectation to carry: rapidhash is a general purpose hash for speed, not a keyed MAC for hostile input.

If your keys can be chosen by someone else, for instance a network protocol, you need a keyed construction with a secret you generate and keep out of the binary. Whether rapidhash supports that directly is a question for the source, not for this review.

The adopters are the strongest argument for the design

The README lists where rapidhash is already used: Chromium, NodeJS, Folly's F14, Fuchsia, Ninja, JuliaLang, ziglang, fb303 and zxc. That list spans a browser engine, a JavaScript runtime, a C++ utility library, an operating system, a build tool, a dynamic language runtime, a systems language and a Facebook library. It is a reasonable signal that the implementation survives compilers and codebases that a smaller project never has to survive.

Note the shape of that list. Every entry is a system that hashes a great deal of data, and most of them hash short identifiers: object keys, symbol names, file paths, interned strings. That is precisely the regime the benchmarks cover, and it explains the design bias toward short inputs. The measurements average latency for keys of 4, 8 and 16 bytes, and peak throughput for files of 16Kb to 2Mb.

There is a second-order lesson here about the ports. The README lists implementations in Java through hash4j, Rust through hoxxep, JavaScript through komiya-atsushi, Go through dwisiswant0 and C# through Molth's Hashing library. A Java or Go user is not vendoring the C++ header, and the behaviour of a port, including its seeding and streaming support, is a property of that port's author. The README does not state that the ports are byte-for-byte identical to the C++ original, so treat cross-language hash equality as something to verify if you plan to persist hashes across services.

The old_version/ directory is there as well, which is the usual sign that the hash output has changed across versions at some point. If you are storing hashes for later comparison, pin a version and record it.

Collision counts sit close to the binomial expectation

Quality is presented in a form that can be checked rather than asserted. The README lays out the ideal: a 64-bit hash should produce each output with probability 1/2^64, so hashing n distinct keys should yield about (n*(n-1))/2^65 collisions, which works out to 7.03 expected collisions for 15 times 2^30 keys. The experiment hashed 68 datasets of 15Gi keys and recorded the collisions in each, with the average across datasets coming to 7.60, described as 8.11 percent over the 7.03 expectation.

A second, larger table covers input lengths from 12 to 128 bytes at two dataset sizes. At 15Gi keys, observed collisions run from 4 to 11 against an expectation of 7.0. At 62Gi keys, expectation is 120.1 and observed values run from 97 to 180. The spread is what you would expect from a binomial distribution, and the README frames the ideal as exactly that, a binomial distribution of results across datasets.

Read those numbers carefully and the takeaway is narrow but solid: for the key lengths tested, the output behaves close to a uniform 64-bit function. That is a statement about distribution, not about resistance. A hash with ideal distribution is still fully attackable if the attacker knows the seed, and the study used the default seed 0.

The tests are external as well. The README states that all functions pass all tests in both SMHasher and SMHasher3, and that SMHasher and SMHasher3 list rapidhash among the fastest recommended hash functions, with links to the raw result files for both. Independent test suites are the right place to look for this kind of claim, since the project's own collision program measures the same property it designed for.

Where the numbers land against xxh3, and when to pick something else

The README benchmarks against xxh3, and the two tables are the most useful part of the performance claim because they include a case where rapidhash is not ahead.

For average latency on 4, 8 and 16 byte keys, rapidhash records 1.79ns on M1 Pro and 1.38ns on M3 Pro, against 1.92ns and 1.50ns for xxh3. The margin on those machines is small, under 10 percent. On Neoverse V2 the two are 2.05ns and 2.15ns, and on AMD Turin they are 2.31ns and 2.35ns, which is a gap of about 2 percent. On Ryzen 9700X, xxh3 is 1.45ns and rapidhash is 1.46ns, effectively a tie.

Peak throughput on 16Kb to 2Mb files is where the difference is larger. On M1 Pro the numbers are 47GB/s against 37GB/s, on M3 Pro 57GB/s against 43GB/s, on M3 Ultra 61GB/s against 47GB/s, and on M4 71GB/s against 49GB/s, which is where the README's claim of surpassing 70GB/s on Apple's M4 cpus comes from. On Neoverse V2 it is 38GB/s against 34GB/s. On Ryzen 9700X, though, xxh3 reaches 78GB/s and rapidhash 68GB/s, so rapidhash loses on that machine. The long input measurements were taken with the RAPIDHASH_UNROLLED macro defined, and the benchmarking program sits in the bench/ folder.

The real alternative is therefore not a superior function but a different shape. rapidhash gives you three code sizes and streamable input; xxh3 is a single implementation with its own ecosystem. RapidhashNano with its sub 100 instruction target is the option that no general purpose alternative in that table offers. For a hash table with short string keys, the latency difference of a few tenths of a nanosecond is rarely the deciding factor, and the choice of hash map, key layout and cache behaviour will dominate it.

Editorial conclusion

Rapidhash suits C++ developers choosing a general purpose hash for a hash table, cache or build system, and it suits embedded work through rapidhashNano when code size dominates. It is the wrong choice for anything that must resist a deliberate collision attack, since the README states plainly that the functions use no cryptographic instruction sets and the experiments ran with the default seed 0, and it is a poor fit if you need a documented, versioned upstream library with a supported release channel, because the only published artefacts are three 2025 tags. Before you adopt it, check the last push date on the master branch, read the seed and secret handling in rapidhash.h and secret.h for your threat model, and benchmark the size of your real keys rather than trusting the 48 byte and 512 byte crossover points.

Frequently asked questions

What is the difference between rapidhash, rapidhashMicro and rapidhashNano?

They differ in compiled code size and behaviour on long inputs. The general function compiles to about 185 instructions, Micro to about 140 without stack usage, and Nano to less than 100 without stack usage, with Micro faster up to 512 bytes and Nano fastest up to 48 bytes.

How do I add rapidhash to a C++ project?

The repository has no build file or install script, and its top level contains rapidhash.h and secret.h. The README does not publish a package manager command or an installation step, so the header has to be vendored into your source tree by hand, or you can use one of the listed ports for Java, Rust, JavaScript, Go or C#.

Is rapidhash suitable for hashing untrusted or attacker controlled input?

The README states that the functions do not use machine specific vectorized or cryptographic instruction sets, and the collision study used the default seed 0. It is a fast general purpose hash rather than a keyed construction for hostile input.

Is rapidhash still being updated?

The repository is not archived and the last push was on 2026-08-19, on the master branch. The most recent published release tags are rapidhash_v3 from 2025-08-16 and rapidhash_v2.2 and rapidhash_v2.1 from 2025-05-20.

Can I use the same hash value in a C++ service and a Go service?

The README lists a Go port by dwisiswant0 alongside Java, Rust, JavaScript and C# ports, but it does not state that the ports produce identical output to the C++ original. If hashes are persisted across languages, verify the port produces the same values before relying on it.

Official sources

  1. Issues
  2. License: MIT
  3. Nicoshev/rapidhash on GitHub
  4. README
  5. Releases
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/nicoshev-rapidhash.svg)](https://hysenlabs.com/projects/nicoshev-rapidhash)

Was this useful?