# F14 Hash Table F14 is a 14-way probing hash table that resolves collisions by double hashing. Up to 14 keys are stored in a chunk at a single hash table position. Vector instructions (SSE2 on x86_64, NEON on aarch64) are used to filter within a chunk; intra-chunk search takes only a handful of instructions. **F14** refers to the fact that the algorithm **F**ilters up to **14** keys at a time. This strategy allows the hash table to be operated at a high maximum load factor (12/14) while still keeping probe chains very short. F14 provides compelling replacements for most of the hash tables we use in production at Facebook. Switching to it can improve memory efficiency and performance at the same time. The hash table implementations widely deployed in C++ at Facebook exist along a spectrum of space/time tradeoffs. The fastest is the least memory efficient, and the most memory efficient (google::sparse_hash_map) is much slower than the rest. F14 moves the curve, simultaneously improving memory efficiency and performance when compared to most of the existing algorithms. ## F14 VARIANTS The core hash table implementation has a pluggable storage strategy, with three policies provided: F14NodeMap stores values indirectly, calling malloc on each insert like std::unordered_map. This implementation is the most memory efficient for medium and large keys. It provides the same iterator and reference stability guarantees as the standard map while being faster and more memory efficient, so you can substitute F14NodeMap for std::unordered_map safely in production code. F14's filtering substantially reduces indirection (and cache misses) when compared to std::unordered_map. F14ValueMap stores values inline, like google::dense_hash_map. Inline storage is the most memory efficient for small values, but for medium and large values it wastes space. Because it can tolerate a much higher load factor, F14ValueMap is almost twice as memory efficient as dense_hash_map while also faster for most workloads. F14VectorMap keeps values packed in a contiguous array. The main hash array stores 32-bit indexes into the value vector. Compared to the existing internal implementations that use a similar strategy, F14 is slower for simple keys and small or medium-sized tables (because of the cost of bit mixing), faster for complex keys and large tables, and saves about 16 bytes per entry on average. We also provide: F14FastMap inherits from either F14ValueMap or F14VectorMap depending on entry size. When the key and mapped_type are less than 24 bytes, it inherits from F14ValueMap. For medium and large entries, it inherits from F14VectorMap. This strategy provides the best performance, while also providing better memory efficiency than dense_hash_map or the other hash tables in use at Facebook that don't individually allocate nodes. ## WHICH F14 VARIANT IS RIGHT FOR ME? F14FastMap is a good default choice. If you care more about memory efficiency than performance, F14NodeMap is better for medium and large entries. F14NodeMap is the only F14 variant that doesn't move its elements, so in the rare case that you need reference stability you should use it. ## HETEROGENEOUS KEY TYPE WITH TRANSPARENT HASH AND EQUALITY In some cases it makes sense to define hash and key equality across types. For example, StringPiece's hash and equality are capable of accepting std::string (because std::string is implicitly convertible to StringPiece). If you mark the hash functor and key equality functor as _transparent_, then F14 will allow you to search the table directly using any of the accepted key types without converting the key. For example, using H = folly::transparent> and E = folly::transparent>, an F14FastSet will allow you to use a StringPiece key without the need to construct a std::string. Heterogeneous lookup and erase works for any key types that can be passed to operator() on the hasher and key_equal functors. For operations such as operator[] that might insert there is an additional constraint, which is that the passed-in key must be explicitly convertible to the table's key_type. F14 maps understand all possible forms that can be used to construct the underlying std::pair * Xiao Shi --