Open-source project
greg7mdp/parallel-hashmap avatar
greg7mdp/parallel-hashmap

parallel-hashmap: header-only flat and node hash maps for C++11 and later

A family of header-only, very fast and memory-friendly hashmap and btree containers.

3,219 stars313 forksC++Apache-2.0

At a glance

What is it?
greg7mdp/parallel-hashmap is a header-only family of hash and btree containers that drop into existing code. It is fast and compact, but the README now points new work at gtl, which changes the adoption calculus.
Who is it for?
Adopt parallel-hashmap if you are pinned to C++11, C++14 or C++17 and want a drop-in replacement for std::unordered_map, std::unordered_set, std::map or std::set without adding a build dependency: copy the parallel_hashmap directory, include phmap.h or btree.h, and keep your existing container API. Do not adopt it for a new C++20 codebase, because the README recommends gtl in that case and states that new development happens there.
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 20 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 September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What parallel-hashmap replaces, and who is it for

The repository targets a narrow, common problem: std::unordered_map and std::unordered_set are convenient but leave performance and memory on the table, and swapping them for something better usually means adding a build dependency or rewriting call sites. parallel-hashmap answers that by being header only. The README states that nothing needs to be built: you copy the parallel_hashmap directory into your project and you are done. It also describes the containers as drop-in replacements for std::unordered_map, std::unordered_set, std::map and std::set, so existing code that uses the standard interfaces keeps compiling.

The audience is C++ teams with older toolchains. The README requires only a C++11 compiler, while also providing C++14 and C++17 APIs such as try_emplace. That matters for codebases that cannot move to C++20 but still want faster lookups. A second group benefits too: anyone whose container memory footprint shows up in a profile. The README calls the library memory friendly, with the honest caveat that usage is a little higher than sparsepp.

The project also ships btree containers, described as direct ports from Abseil, as an ordered alternative to std::map and std::set. So the same directory covers both the unordered and the ordered case, which is unusual for a single header-only dependency.

How the flat hash map avoids pointer chasing

The design is closed hashing. The README explains that values are stored directly into a memory array, avoiding memory indirections, which is the main reason a flat map beats a node-based one on lookup-heavy workloads. Each element is not a separately allocated node reached through a pointer.

The lookup mechanism is the part worth understanding before you adopt it. The README states that the hashmaps use parallel SSE2 instructions to check 16 slots at once, which lets the implementation stay fast even when the table is filled up to 87.5% capacity. That load factor is the practical payoff: a table that stays fast when nearly full wastes less memory on empty buckets.

The library is not written from scratch. The README says the hashmaps and btree are built upon those open sourced by Google in the Abseil library, and carries an explicit warning that this repository borrows code from abseil-cpp with modifications and may behave differently from the original. Treat it as an independent work rather than a supported Abseil build.

Two API details are easy to miss. Heterogeneous lookup is supported, and boost's hash_value() method is picked up automatically, with default hash support for std::pair and std::tuple. The header parallel_hashmap/phmap.h provides eight hash tables in total: flat, node and parallel variants of map and set. The parallel_ variants are the ones that matter for multi-threaded writes, and they are distinct types, not a flag on the flat ones.

Installing parallel-hashmap and a first flat_hash_map example

There is no package to install. The README's instruction is to copy the parallel_hashmap directory to your project and update your include path. The README's own example uses phmap::flat_hash_map with std::string keys and values, initializes it from a brace-enclosed list, iterates it, and then inserts with operator[]. The include line is the only change from the standard container.

c++
#include <iostream>
#include <string>
#include <parallel_hashmap/phmap.h>

using phmap::flat_hash_map;

int main()
{
    flat_hash_map<std::string, std::string> email =
    {
        { "tom",  "[email protected]"},
        { "jeff", "[email protected]"},
        { "jim",  "[email protected]"}
    };

    for (const auto& n : email)
        std::cout << n.first << "'s email is: " << n.second << "\n";

    email["bill"] = "[email protected]";
    std::cout << "bill's email is: " << email["bill"] << "\n";
    return 0;
}

Compile it with your normal flags; no link step is added. If you want the upstream tests and examples instead of a hand-written program, the README gives a CMake invocation with the PHMAP_BUILD_TESTS and PHMAP_BUILD_EXAMPLES options, followed by a build and ctest run.

sh
cmake -DPHMAP_BUILD_TESTS=ON -DPHMAP_BUILD_EXAMPLES=ON -B build
cmake --build build
ctest --test-dir build

Visual Studio users have one extra step the README mentions: adding phmap.natvis to the project so the debugger shows hash table contents clearly. The repository also contains phmap_gdb.py and phmap_lldb.py for the GDB and LLDB side, though the README does not describe their usage.

Where parallel-hashmap is the wrong choice

The most important limitation is stated at the top of the README, not buried in a footnote. The project encourages phmap users to switch to gtl if possible, notes that gtl provides the same functionality but requires C++20 or above, and says that support for issues and new features will eventually move exclusively to gtl. New C++20 projects should read that as a direct instruction and start with gtl instead. parallel-hashmap remains the right pick only when the compiler floor forces it.

There are smaller edges. Forward declaration works by including phmap_fwd_decl.h in your headers, but the README flags that this does not currently work for hash maps with pointer keys, which is exactly the case where you might want to hide a heavy header. The dump/load feature, which writes a flat table to disk as a single array without hash computation, applies only to flat hash maps and sets, only when the stored data is std::trivially_copyable, and the README notes it uses 10% to 60% extra disk space. That trade is fine for a cache file and wrong for a format you must keep small.

The Abseil provenance cuts both ways. The README states plainly that the code is borrowed with modifications and may behave differently from the original, and that the repository is an independent work with no guarantees implied or provided by the authors. If your organisation already depends on Abseil, or needs Abseil's support commitments, going through this fork adds a divergence you would have to track yourself. And because the library is header only, every translation unit that includes phmap.h recompiles the implementation; there is no shared object to amortise that cost.

parallel-hashmap versus Abseil and sparsepp

The two comparisons the README itself makes are the useful ones. Against Abseil, the difference is packaging and toolchain, not algorithm: the README says these containers are built upon code open sourced in Abseil, so the flat hash map design descends from absl::flat_hash_map. Choosing parallel-hashmap over Abseil means accepting a modified fork in exchange for a single copied directory and a C++11 floor, and accepting that the fork may behave differently from the original.

Against sparsepp, the difference is the memory and speed trade. The README claims the containers are significantly faster than the compiler's unordered map or set, than Boost's, and than sparsepp, while describing memory usage as low but a little higher than sparsepp. So sparsepp is the option to look at when footprint is the binding constraint and some lookup speed is expendable; parallel-hashmap is the option when you want both but are willing to give up a little memory to get the speed.

Neither comparison covers the btree containers. The README says the btree containers are direct ports from Abseil and should behave exactly the same as the originals, so there the decision is purely about how you want to consume the code, not about behaviour.

Licence and the cost of keeping it current

The licence is Apache-2.0, shown in the README badge and present as a LICENSE file at the repository root. That is the same licence family as Abseil, which is consistent with the borrowed code, and it is permissive enough for commercial use. This is not legal advice; if you vendor the directory into a product, your own process decides how attribution and notice files are handled.

Upgrade cost is low by construction. There is no binary to rebuild, no ABI to match, and no version pinned in a package manager, so moving to a newer revision is a directory replacement plus a recompile. The repository's last push was on 2026-09-10, and the most recent tagged release listed is v2.0.0 from 2025-01-21, after v1.4.1 in October 2024 and v1.4.0 in September 2024. The README states that new features will eventually move to gtl, so the realistic upgrade path for a long-lived project is a migration to gtl once the C++20 floor is acceptable, not an indefinite series of phmap updates. Budget for that migration rather than treating this as a dependency you will keep forever.

Editorial conclusion

Adopt parallel-hashmap if you are pinned to C++11, C++14 or C++17 and want a drop-in replacement for std::unordered_map, std::unordered_set, std::map or std::set without adding a build dependency: copy the parallel_hashmap directory, include phmap.h or btree.h, and keep your existing container API. Do not adopt it for a new C++20 codebase, because the README recommends gtl in that case and states that new development happens there. Before committing, verify three things in your own tree: that your toolchain matches one of the tested compilers listed in the README, that your key types work with heterogeneous lookup if you rely on it, and that the forward-declaration header is not needed for pointer-keyed maps, since the README notes that case does not work. The dump/load path is worth checking only for flat maps and sets holding std::trivially_copyable values.

Frequently asked questions

How do I install parallel-hashmap in a C++ project?

Copy the parallel_hashmap directory into your project and update your include path. There is nothing to build, since the library is header only, and the README's example includes parallel_hashmap/phmap.h directly.

Is parallel-hashmap a drop-in replacement for std::unordered_map?

The README describes the containers as drop-in replacements for std::unordered_map, std::unordered_set, std::map and std::set, and the example uses phmap::flat_hash_map with the same initialization, iteration and operator[] syntax.

Should I use parallel-hashmap or gtl?

The README recommends gtl if you compile with C++20 or higher, and parallel-hashmap otherwise, since gtl requires C++20 while this repository only requires C++11. It also states that new development happens in gtl and that issue and feature support will eventually move there exclusively.

What does the dump/load feature in parallel-hashmap require?

It applies to flat hash maps and sets only, and only when the stored data is std::trivially_copyable. The README says the table is dumped and restored as a single array without hash computation, using 10% to 60% extra disk space.

Can parallel-hashmap containers be forward declared?

Yes, by including phmap_fwd_decl.h in your header files. The README notes that this does not currently work for hash maps with pointer keys.

Official sources

  1. greg7mdp/parallel-hashmap on GitHub
  2. License: Apache-2.0
  3. Project website
  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/greg7mdp-parallel-hashmap.svg)](https://hysenlabs.com/projects/greg7mdp-parallel-hashmap)