{"id":26337034,"url":"https://github.com/yasushi-saito/inlined_hash_table","last_synced_at":"2025-07-14T02:32:51.885Z","repository":{"id":139545896,"uuid":"88804807","full_name":"yasushi-saito/inlined_hash_table","owner":"yasushi-saito","description":"Fast open-addressed C++ hash table","archived":false,"fork":false,"pushed_at":"2018-03-20T23:18:46.000Z","size":72,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-16T02:18:26.189Z","etag":null,"topics":["cpp","hashing","hashtable"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yasushi-saito.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-20T00:54:10.000Z","updated_at":"2018-03-21T00:21:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"3f45fc3a-db58-4a91-8a16-928625bb5aff","html_url":"https://github.com/yasushi-saito/inlined_hash_table","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yasushi-saito/inlined_hash_table","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasushi-saito%2Finlined_hash_table","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasushi-saito%2Finlined_hash_table/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasushi-saito%2Finlined_hash_table/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasushi-saito%2Finlined_hash_table/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yasushi-saito","download_url":"https://codeload.github.com/yasushi-saito/inlined_hash_table/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasushi-saito%2Finlined_hash_table/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265233753,"owners_count":23731825,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","hashing","hashtable"],"created_at":"2025-03-16T02:17:27.185Z","updated_at":"2025-07-14T02:32:51.842Z","avatar_url":"https://github.com/yasushi-saito.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InlinedHashTable and HopScotchHashTable\n\nInlinedHashTable is a fast open-addressed C++ hash table.  It is very similar to\ngoogle's\n[dense hash map](http://goog-sparsehash.sourceforge.net/doc/dense_hash_map.html),\nbut it's takes less memory. HopScotchHashTable is an implementation of the\nfollowing paper.  It is _not_ thread safe; it's merely thread compatible.\n\n[Hopscotch hashing](https://pdfs.semanticscholar.org/48c2/af3d559fb2c7ef5e71efd24ab5ae217c1fee.pdf),\nMaurice Herlihy, Nir Shavit, Moran Tzafrir.\n\n`InlinedHashTable` is small, simple and fast, especially when keys and values\nare small (think integers and floating points). The downside is that it needs\ntwo special keys, _empty key_ and _deleted keys_ to represent empty slots and\ntombstones. Besides a just bit cumbersome to configure, these two cannot be used\nas regular keys.\n\n`HopScotchHashTable` is a bit slower than `InlinedHashTable` but faster than\n`std::unordered_map`. It doesn't require empty nor deleted keys. One of the\nadvantages of this algorithm is that it uses linear probing to handle\ncollisions, but yet it can handle very high load factor. So it should perform\nbetter on a very large data set.\n\n## Prerequisites\n\nYou need a C++-11 compiler. I tested using gcc-4.8/libstdc++ and clang-4.0/libc++.\nTo run the test and benchmark, you need to install google sparsehash. For ubuntu, do:\n\n    sudo apt-get install g++ libsparsehash-dev\n\nFollow the following descriptions to install gtest:\n\n    https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/\n\nTo build the test:\n\n    cmake .\n    make -j8\n\n\n## Installation\n\nThe library consists of a single header file with no extra dependency. Just copy\nit to where you want.\n\nThe cmakefiles are for unittests, and you can ignore them.\n\n### Using InlinedHashTable\n\nSee the header file for more details.\n\n```\nclass Options {\n public:\n  static constexpr int EmptyKey() { return -1; }  // required\n  static constexpr int DeletedKey() { return -2; }  // optional\n  static constexpr double MaxLoadFactor() { return 0.75; } // optional\n};\n\nusing Map = InlinedHashMap\u003cint, int, 8, Options\u003e;\n\nvoid Test() {\n  Map map;\n  map[1] = 2;\n  map[3] = 4;\n  for (auto [key, value] : map) {\n     printf(\"entry %d %d\\n\", key, value);\n  }\n}\n```\n\nThe above example creates an integer→integer hash map. It uses -1 as an empty\nkey, and -2 as the deleted key (tombstones).  After erasing an existing element,\nthe bucket is set to -2. You cannot use -1 or -2 as a valid key. `DeletedKey()`\nis needed only when `InlinedHashTable::erase()` is going to be used.\n\nThe third parameter, `8`, defines the number of elements stored in-line with the\nhash map. That is, up to 8 elements can be stored in the hash table without\n`new`. It is allowed to set this parameter to 0.\n\n### Iterator invalidation semantics for InlinedHashTable\n\nIt's the same as dense\\_hash\\_map's, and is weaker than std::unordered\\_map's:\n\n- Insertion invalidates outstanding iterators.\n\n- Erasure keeps iterators valid, except those referring to the element being\n  erased.\n\n## Using HopScotchHashTable\n\nSee the header file for more details. The template parameters are the same as\n`std::unordered_map`s. Iterator invalidation semantics is the same as\nInlinedHashTable.\n\n## Performance\n\nLookup and insert are faster than std::unordered_map, and in par with\ndense\\_hash\\_map. inlined\\_hash\\_map has much smaller memory footprint for small\ntables. An empty dense\\_hash\\_map takes 88 bytes, whereas inlined\\_hash\\_map\ntakes 24 bytes, so if you create lots of small maps, the latter will start\nperforming better.\n\nThe following tests are done on clang++(4.0) on a Haswell-grade CPU. We used\ntcmalloc for memory allocation.  The numbers after \"/\" are the number of\nelements inserted or looked up.\n\n\u003cpre\u003e\nBM_Insert_HopScotchMap_Int/4                   943 ns        943 ns     604541\nBM_Insert_HopScotchMap_Int/8                  1052 ns       1052 ns     664131\nBM_Insert_HopScotchMap_Int/64                 2526 ns       2525 ns     277414\nBM_Insert_HopScotchMap_Int/512               29075 ns      29085 ns      24100\nBM_Insert_HopScotchMap_Int/4096             282043 ns     282080 ns       2481\nBM_Insert_HopScotchMap_Int/32768           2543595 ns    2543481 ns        276\nBM_Insert_HopScotchMap_Int/262144         20309576 ns   20308259 ns         34\nBM_Insert_HopScotchMap_Int/1048576       101457974 ns  101448429 ns          7\nBM_Insert_InlinedMap_Int/4                     845 ns        845 ns     827415\nBM_Insert_InlinedMap_Int/8                     868 ns        869 ns     812258\nBM_Insert_InlinedMap_Int/64                   1579 ns       1579 ns     443574\nBM_Insert_InlinedMap_Int/512                  5946 ns       5947 ns     116834\nBM_Insert_InlinedMap_Int/4096                86386 ns      86417 ns       8124\nBM_Insert_InlinedMap_Int/32768              826286 ns     826297 ns        848\nBM_Insert_InlinedMap_Int/262144           13224904 ns   13224163 ns         53\nBM_Insert_InlinedMap_Int/1048576          59225263 ns   59219832 ns         12\nBM_Insert_UnorderedMap_Int/4                   811 ns        810 ns     858459\nBM_Insert_UnorderedMap_Int/8                   895 ns        894 ns     784535\nBM_Insert_UnorderedMap_Int/64                 2420 ns       2420 ns     290581\nBM_Insert_UnorderedMap_Int/512               16677 ns      16682 ns      42058\nBM_Insert_UnorderedMap_Int/4096             184362 ns     184355 ns       3765\nBM_Insert_UnorderedMap_Int/32768           2529515 ns    2529361 ns        277\nBM_Insert_UnorderedMap_Int/262144         31579244 ns   31575242 ns         22\nBM_Insert_UnorderedMap_Int/1048576       151387016 ns  151371978 ns          5\nBM_Insert_DenseHashMap_Int/4                   802 ns        802 ns     872195\nBM_Insert_DenseHashMap_Int/8                   847 ns        847 ns     826408\nBM_Insert_DenseHashMap_Int/64                 1804 ns       1802 ns     387969\nBM_Insert_DenseHashMap_Int/512                9867 ns       9879 ns      70510\nBM_Insert_DenseHashMap_Int/4096             110718 ns     110745 ns       6318\nBM_Insert_DenseHashMap_Int/32768           1325141 ns    1325071 ns        528\nBM_Insert_DenseHashMap_Int/262144         11938077 ns   11937301 ns         58\nBM_Insert_DenseHashMap_Int/1048576        63407206 ns   63401394 ns         11\nBM_Lookup_HopScotchMap_Int/4                    16 ns         16 ns   45118013\nBM_Lookup_HopScotchMap_Int/8                    27 ns         27 ns   25819569\nBM_Lookup_HopScotchMap_Int/64                  228 ns        228 ns    3062728\nBM_Lookup_HopScotchMap_Int/512                1553 ns       1553 ns     451592\nBM_Lookup_HopScotchMap_Int/4096              20555 ns      20553 ns      34254\nBM_Lookup_HopScotchMap_Int/32768            300977 ns     300948 ns       2333\nBM_Lookup_HopScotchMap_Int/262144          3456593 ns    3456249 ns        226\nBM_Lookup_HopScotchMap_Int/1048576        28870478 ns   28867499 ns         24\nBM_Lookup_InlinedMap_Int/4                      10 ns         10 ns   69227338\nBM_Lookup_InlinedMap_Int/8                      14 ns         14 ns   49921994\nBM_Lookup_InlinedMap_Int/64                     91 ns         91 ns    7061233\nBM_Lookup_InlinedMap_Int/512                   695 ns        695 ns    1019383\nBM_Lookup_InlinedMap_Int/4096                 8734 ns       8733 ns      84831\nBM_Lookup_InlinedMap_Int/32768              213709 ns     213687 ns       3284\nBM_Lookup_InlinedMap_Int/262144            1058658 ns    1058555 ns        663\nBM_Lookup_InlinedMap_Int/1048576          10901019 ns   10899926 ns         65\nBM_Lookup_UnorderedMap_Int/4                    24 ns         24 ns   29666537\nBM_Lookup_UnorderedMap_Int/8                    53 ns         53 ns   13037353\nBM_Lookup_UnorderedMap_Int/64                  356 ns        356 ns    1971142\nBM_Lookup_UnorderedMap_Int/512                3099 ns       3098 ns     225246\nBM_Lookup_UnorderedMap_Int/4096              40833 ns      40830 ns      17003\nBM_Lookup_UnorderedMap_Int/32768            492502 ns     492451 ns       1422\nBM_Lookup_UnorderedMap_Int/262144          4854618 ns    4854140 ns        145\nBM_Lookup_UnorderedMap_Int/1048576        48787983 ns   48783085 ns         14\nBM_Lookup_DenseHashMap_Int/4                     7 ns          7 ns  102440344\nBM_Lookup_DenseHashMap_Int/8                    13 ns         13 ns   55428597\nBM_Lookup_DenseHashMap_Int/64                  117 ns        117 ns    6017370\nBM_Lookup_DenseHashMap_Int/512                 947 ns        947 ns     745749\nBM_Lookup_DenseHashMap_Int/4096              19644 ns      19642 ns      35107\nBM_Lookup_DenseHashMap_Int/32768            230975 ns     230953 ns       3016\nBM_Lookup_DenseHashMap_Int/262144          1903844 ns    1903660 ns        369\nBM_Lookup_DenseHashMap_Int/1048576        16903422 ns   16901719 ns         41\nBM_Insert_HopScotchMap_String/4               1081 ns       1080 ns     648769\nBM_Insert_HopScotchMap_String/8               1384 ns       1383 ns     505411\nBM_Insert_HopScotchMap_String/64              5113 ns       5109 ns     136416\nBM_Insert_HopScotchMap_String/512            62336 ns      62333 ns      11218\nBM_Insert_HopScotchMap_String/4096          654178 ns     654153 ns       1066\nBM_Insert_HopScotchMap_String/32768        5926282 ns    5925871 ns        119\nBM_Insert_HopScotchMap_String/262144      81605466 ns   81596382 ns          9\nBM_Insert_HopScotchMap_String/1048576    398059140 ns  398023573 ns          2\n\u003c/pre\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyasushi-saito%2Finlined_hash_table","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyasushi-saito%2Finlined_hash_table","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyasushi-saito%2Finlined_hash_table/lists"}