/swiss

Go port of Google's Swiss Table hash table

Primary LanguageGoApache License 2.0Apache-2.0

Swiss Map Build Status GoDoc

swiss.Map is a Go implementation of Google's Swiss Tables hash table design. The Rust version of Swiss Tables is now the HashMap implementation in the Rust standard library.

A swiss.Map[K,V] maps keys of type K to values of type V, similar to Go's builtin map[K]V type. The primary advantage of swiss.Map over Go's builtin map is performance. swiss.Map has similar or slightly better performance than Go's builtin map for small map sizes, and significantly better performance at large map sizes. The benchmarks where swiss.Map performs worse are due to a fast-path optimization in Go's builtin maps for tiny (6 or fewer element) maps with int32, int64, or string keys, and when growing a map. In the latter case, Go's builtin map is somewhat more parsimonious with allocations at small map sizes and the performance hit of the extra allocation dominates in the operations.

Performance: Go's builtin map (old) vs swiss.Map (new)

Tested on a GCE n1-standard-16 instance.

goos: linux
goarch: amd64
pkg: github.com/cockroachdb/swiss
cpu: Intel(R) Xeon(R) CPU @ 2.60GHz

name                               old time/op    new time/op    delta
MapIter/Int/6-16                     70.3ns ± 0%    39.2ns ± 3%    -44.25%  (p=0.000 n=9+9)
MapIter/Int/12-16                     120ns ± 1%      58ns ± 2%    -51.72%  (p=0.000 n=8+9)
MapIter/Int/18-16                     187ns ± 3%      90ns ± 2%    -51.99%  (p=0.000 n=10+10)
MapIter/Int/24-16                     223ns ± 3%      96ns ± 1%    -57.17%  (p=0.000 n=10+10)
MapIter/Int/30-16                     301ns ± 3%     134ns ± 1%    -55.38%  (p=0.000 n=9+10)
MapIter/Int/64-16                     584ns ± 3%     237ns ± 0%    -59.51%  (p=0.000 n=10+8)
MapIter/Int/128-16                   1.15µs ± 2%    0.42µs ± 1%    -63.03%  (p=0.000 n=9+10)
MapIter/Int/256-16                   2.40µs ± 4%    0.80µs ± 1%    -66.55%  (p=0.000 n=10+10)
MapIter/Int/512-16                   5.12µs ± 2%    1.55µs ± 1%    -69.68%  (p=0.000 n=10+10)
MapIter/Int/1024-16                  10.9µs ± 2%     3.0µs ± 1%    -72.13%  (p=0.000 n=10+10)
MapIter/Int/2048-16                  22.4µs ± 1%     6.1µs ± 0%    -72.82%  (p=0.000 n=9+10)
MapIter/Int/4096-16                  45.3µs ± 2%    23.4µs ± 4%    -48.38%  (p=0.000 n=10+10)
MapIter/Int/8192-16                  90.6µs ± 1%    71.0µs ± 1%    -21.65%  (p=0.000 n=9+10)
MapIter/Int/65536-16                  724µs ± 1%     663µs ± 1%     -8.43%  (p=0.000 n=9+9)
MapGetHit/Int64/6-16                 4.93ns ± 0%    6.54ns ± 0%    +32.72%  (p=0.000 n=10+8)
MapGetHit/Int64/12-16                7.33ns ± 3%    6.57ns ± 1%    -10.34%  (p=0.000 n=9+8)
MapGetHit/Int64/18-16                8.16ns ± 7%    6.56ns ± 1%    -19.57%  (p=0.000 n=9+9)
MapGetHit/Int64/24-16                7.36ns ± 2%    6.81ns ± 8%     -7.38%  (p=0.000 n=10+10)
MapGetHit/Int64/30-16                6.93ns ± 1%    6.55ns ± 0%     -5.54%  (p=0.000 n=10+8)
MapGetHit/Int64/64-16                7.00ns ± 1%    6.69ns ± 5%     -4.43%  (p=0.000 n=9+10)
MapGetHit/Int64/128-16               7.06ns ± 2%    6.83ns ± 4%     -3.25%  (p=0.001 n=10+10)
MapGetHit/Int64/256-16               7.12ns ± 2%    6.73ns ± 3%     -5.47%  (p=0.000 n=10+10)
MapGetHit/Int64/512-16               7.11ns ± 2%    6.70ns ± 3%     -5.70%  (p=0.000 n=10+10)
MapGetHit/Int64/1024-16              7.22ns ± 1%    6.82ns ± 2%     -5.45%  (p=0.000 n=9+10)
MapGetHit/Int64/2048-16              8.93ns ± 5%    7.06ns ± 1%    -20.94%  (p=0.000 n=9+10)
MapGetHit/Int64/4096-16              16.3ns ± 2%     8.7ns ± 0%    -46.43%  (p=0.000 n=9+9)
MapGetHit/Int64/8192-16              19.5ns ± 2%     9.2ns ± 0%    -52.86%  (p=0.000 n=10+10)
MapGetHit/Int64/65536-16             25.7ns ± 1%    14.0ns ± 1%    -45.57%  (p=0.000 n=10+7)
MapGetHit/Int32/6-16                 5.14ns ± 0%    6.51ns ± 0%    +26.67%  (p=0.000 n=10+8)
MapGetHit/Int32/12-16                7.53ns ± 5%    6.84ns ±15%     -9.14%  (p=0.001 n=10+10)
MapGetHit/Int32/18-16                7.92ns ±17%    6.52ns ± 0%    -17.68%  (p=0.000 n=10+10)
MapGetHit/Int32/24-16                7.51ns ± 7%    6.69ns ± 8%    -10.96%  (p=0.000 n=10+10)
MapGetHit/Int32/30-16                6.97ns ± 4%    6.53ns ± 0%     -6.27%  (p=0.000 n=10+10)
MapGetHit/Int32/64-16                7.13ns ± 5%    6.73ns ± 6%     -5.60%  (p=0.011 n=10+10)
MapGetHit/Int32/128-16               7.18ns ± 2%    6.77ns ± 5%     -5.77%  (p=0.000 n=10+10)
MapGetHit/Int32/256-16               7.21ns ± 3%    6.73ns ± 5%     -6.66%  (p=0.000 n=10+10)
MapGetHit/Int32/512-16               7.19ns ± 1%    6.72ns ± 1%     -6.53%  (p=0.000 n=10+8)
MapGetHit/Int32/1024-16              7.40ns ± 1%    6.68ns ± 1%     -9.68%  (p=0.000 n=8+9)
MapGetHit/Int32/2048-16              9.19ns ± 3%    6.71ns ± 2%    -26.99%  (p=0.000 n=9+10)
MapGetHit/Int32/4096-16              16.1ns ± 2%     8.2ns ± 0%    -49.33%  (p=0.000 n=10+9)
MapGetHit/Int32/8192-16              19.0ns ± 1%     8.6ns ± 1%    -54.73%  (p=0.000 n=10+10)
MapGetHit/Int32/65536-16             23.7ns ± 1%    11.1ns ± 2%    -53.21%  (p=0.000 n=10+10)
MapGetHit/String/6-16                13.0ns ± 0%     9.3ns ± 0%    -28.55%  (p=0.000 n=8+10)
MapGetHit/String/12-16               9.55ns ±10%    9.29ns ± 0%       ~     (p=0.173 n=10+8)
MapGetHit/String/18-16               10.7ns ± 7%     9.9ns ±13%     -8.01%  (p=0.050 n=10+10)
MapGetHit/String/24-16               9.82ns ±11%   10.86ns ± 2%    +10.60%  (p=0.002 n=10+8)
MapGetHit/String/30-16               8.96ns ± 4%    9.35ns ± 1%     +4.34%  (p=0.000 n=10+9)
MapGetHit/String/64-16               9.20ns ± 4%    9.53ns ± 7%     +3.58%  (p=0.027 n=10+10)
MapGetHit/String/128-16              9.72ns ± 2%    9.46ns ± 3%     -2.62%  (p=0.001 n=10+9)
MapGetHit/String/256-16              10.6ns ± 2%     9.5ns ± 2%     -9.98%  (p=0.000 n=10+10)
MapGetHit/String/512-16              11.2ns ± 1%     9.6ns ± 2%    -14.28%  (p=0.000 n=10+10)
MapGetHit/String/1024-16             11.5ns ± 1%    10.1ns ± 1%    -12.46%  (p=0.000 n=9+10)
MapGetHit/String/2048-16             15.1ns ± 4%    10.2ns ± 1%    -32.59%  (p=0.000 n=10+10)
MapGetHit/String/4096-16             27.5ns ± 1%    12.3ns ± 1%    -55.09%  (p=0.000 n=10+10)
MapGetHit/String/8192-16             30.6ns ± 1%    12.9ns ± 1%    -57.85%  (p=0.000 n=10+10)
MapGetHit/String/65536-16            39.4ns ± 1%    19.2ns ± 3%    -51.39%  (p=0.000 n=10+10)
MapGetMiss/Int64/6-16                6.58ns ± 1%    5.98ns ± 0%     -9.10%  (p=0.000 n=9+8)
MapGetMiss/Int64/12-16               9.73ns ±23%    6.57ns ±12%    -32.50%  (p=0.000 n=10+10)
MapGetMiss/Int64/18-16               8.85ns ± 1%    6.38ns ±11%    -27.89%  (p=0.000 n=8+10)
MapGetMiss/Int64/24-16               12.2ns ±11%     7.0ns ± 3%    -42.27%  (p=0.000 n=9+9)
MapGetMiss/Int64/30-16               8.86ns ± 1%    6.23ns ±10%    -29.69%  (p=0.000 n=10+10)
MapGetMiss/Int64/64-16               8.87ns ± 2%    6.84ns ± 4%    -22.86%  (p=0.000 n=8+10)
MapGetMiss/Int64/128-16              9.59ns ±15%    6.80ns ± 5%    -29.11%  (p=0.000 n=10+10)
MapGetMiss/Int64/256-16              9.41ns ± 6%    7.05ns ± 5%    -25.07%  (p=0.000 n=10+10)
MapGetMiss/Int64/512-16              9.44ns ± 6%    7.08ns ± 4%    -24.99%  (p=0.000 n=10+10)
MapGetMiss/Int64/1024-16             9.24ns ± 3%    7.26ns ± 3%    -21.49%  (p=0.000 n=9+10)
MapGetMiss/Int64/2048-16             10.0ns ± 2%     7.2ns ± 3%    -27.64%  (p=0.000 n=10+10)
MapGetMiss/Int64/4096-16             10.5ns ± 1%    13.9ns ± 5%    +32.92%  (p=0.000 n=10+10)
MapGetMiss/Int64/8192-16             11.1ns ± 1%    15.0ns ±24%    +35.36%  (p=0.000 n=10+10)
MapGetMiss/Int64/65536-16            15.6ns ± 3%    17.4ns ±10%    +11.43%  (p=0.000 n=10+10)
MapGetMiss/Int32/6-16                8.62ns ± 0%    6.13ns ± 6%    -28.86%  (p=0.000 n=9+10)
MapGetMiss/Int32/12-16               10.7ns ± 1%     6.6ns ±11%    -37.98%  (p=0.000 n=8+9)
MapGetMiss/Int32/18-16               10.7ns ± 0%     6.3ns ± 6%    -40.84%  (p=0.000 n=10+10)
MapGetMiss/Int32/24-16               12.6ns ±20%     6.9ns ±10%    -44.81%  (p=0.000 n=10+10)
MapGetMiss/Int32/30-16               10.7ns ± 0%     6.0ns ± 1%    -43.95%  (p=0.000 n=10+8)
MapGetMiss/Int32/64-16               10.7ns ± 0%     6.8ns ± 8%    -36.81%  (p=0.000 n=9+10)
MapGetMiss/Int32/128-16              11.1ns ± 8%     6.9ns ± 4%    -37.67%  (p=0.000 n=10+10)
MapGetMiss/Int32/256-16              11.1ns ± 7%     6.9ns ± 4%    -38.39%  (p=0.000 n=10+10)
MapGetMiss/Int32/512-16              11.0ns ± 4%     7.0ns ± 4%    -36.24%  (p=0.000 n=10+10)
MapGetMiss/Int32/1024-16             11.1ns ± 3%     7.1ns ± 2%    -35.92%  (p=0.000 n=10+10)
MapGetMiss/Int32/2048-16             11.1ns ± 2%     7.1ns ± 2%    -35.74%  (p=0.000 n=10+10)
MapGetMiss/Int32/4096-16             11.2ns ± 3%    14.2ns ± 8%    +26.59%  (p=0.000 n=10+10)
MapGetMiss/Int32/8192-16             11.2ns ± 1%    14.9ns ±25%    +32.64%  (p=0.001 n=10+10)
MapGetMiss/Int32/65536-16            13.7ns ± 1%    17.6ns ± 3%    +28.21%  (p=0.000 n=9+9)
MapGetMiss/String/6-16               7.45ns ± 1%    7.61ns ± 1%     +2.17%  (p=0.000 n=10+8)
MapGetMiss/String/12-16              12.1ns ±15%     8.1ns ±15%    -32.71%  (p=0.000 n=10+10)
MapGetMiss/String/18-16              12.8ns ± 5%     9.2ns ±18%    -28.45%  (p=0.000 n=10+10)
MapGetMiss/String/24-16              14.2ns ±17%     9.5ns ±10%    -33.00%  (p=0.000 n=10+10)
MapGetMiss/String/30-16              11.8ns ± 1%     8.1ns ± 6%    -31.09%  (p=0.000 n=8+10)
MapGetMiss/String/64-16              11.8ns ± 9%     8.5ns ± 6%    -27.58%  (p=0.000 n=10+9)
MapGetMiss/String/128-16             11.8ns ± 5%     8.8ns ± 9%    -25.76%  (p=0.000 n=10+10)
MapGetMiss/String/256-16             11.8ns ± 7%     8.9ns ± 8%    -24.26%  (p=0.000 n=10+10)
MapGetMiss/String/512-16             12.0ns ± 2%     9.0ns ± 6%    -24.90%  (p=0.000 n=10+10)
MapGetMiss/String/1024-16            13.4ns ± 2%     9.0ns ± 3%    -32.64%  (p=0.000 n=10+10)
MapGetMiss/String/2048-16            13.8ns ± 5%     9.1ns ± 1%    -34.32%  (p=0.000 n=10+10)
MapGetMiss/String/4096-16            14.1ns ± 3%    17.9ns ± 3%    +26.71%  (p=0.000 n=10+10)
MapGetMiss/String/8192-16            14.9ns ± 2%    17.6ns ±21%       ~     (p=1.000 n=10+10)
MapGetMiss/String/65536-16           23.8ns ± 2%    21.4ns ±10%    -10.00%  (p=0.000 n=10+10)
MapPutGrow/Int64/6-16                83.5ns ± 0%   143.8ns ± 1%    +72.15%  (p=0.000 n=10+10)
MapPutGrow/Int64/12-16                422ns ± 1%     373ns ± 1%    -11.61%  (p=0.000 n=10+10)
MapPutGrow/Int64/18-16                913ns ± 1%     754ns ± 1%    -17.39%  (p=0.000 n=10+10)
MapPutGrow/Int64/24-16               1.14µs ± 1%    0.83µs ± 2%    -27.58%  (p=0.000 n=9+10)
MapPutGrow/Int64/30-16               2.02µs ± 1%    1.52µs ± 2%    -24.81%  (p=0.000 n=10+10)
MapPutGrow/Int64/64-16               4.64µs ± 1%    2.93µs ± 2%    -36.83%  (p=0.000 n=10+10)
MapPutGrow/Int64/128-16              9.42µs ± 1%    5.73µs ± 2%    -39.20%  (p=0.000 n=10+10)
MapPutGrow/Int64/256-16              18.4µs ± 1%    11.1µs ± 2%    -39.62%  (p=0.000 n=10+10)
MapPutGrow/Int64/512-16              35.8µs ± 1%    21.6µs ± 2%    -39.78%  (p=0.000 n=10+10)
MapPutGrow/Int64/1024-16             71.0µs ± 1%    42.3µs ± 3%    -40.42%  (p=0.000 n=10+10)
MapPutGrow/Int64/2048-16              141µs ± 1%      82µs ± 2%    -41.60%  (p=0.000 n=10+10)
MapPutGrow/Int64/4096-16              282µs ± 1%     184µs ± 1%    -34.69%  (p=0.000 n=10+10)
MapPutGrow/Int64/8192-16              571µs ± 0%     436µs ± 2%    -23.54%  (p=0.000 n=10+10)
MapPutGrow/Int64/65536-16            5.62ms ± 2%    3.96ms ± 2%    -29.51%  (p=0.000 n=10+10)
MapPutGrow/Int32/6-16                83.1ns ± 0%   140.4ns ± 2%    +68.95%  (p=0.000 n=10+10)
MapPutGrow/Int32/12-16                390ns ± 0%     330ns ± 2%    -15.39%  (p=0.000 n=10+10)
MapPutGrow/Int32/18-16                836ns ± 0%     616ns ± 1%    -26.28%  (p=0.000 n=9+10)
MapPutGrow/Int32/24-16               1.06µs ± 1%    0.70µs ± 2%    -33.75%  (p=0.000 n=10+10)
MapPutGrow/Int32/30-16               1.83µs ± 0%    1.23µs ± 2%    -32.95%  (p=0.000 n=10+10)
MapPutGrow/Int32/64-16               4.16µs ± 1%    2.51µs ± 2%    -39.63%  (p=0.000 n=10+10)
MapPutGrow/Int32/128-16              8.46µs ± 1%    5.03µs ± 2%    -40.53%  (p=0.000 n=10+10)
MapPutGrow/Int32/256-16              16.8µs ± 0%    10.0µs ± 3%    -40.30%  (p=0.000 n=9+10)
MapPutGrow/Int32/512-16              32.8µs ± 0%    19.9µs ± 3%    -39.32%  (p=0.000 n=10+10)
MapPutGrow/Int32/1024-16             64.3µs ± 0%    39.1µs ± 2%    -39.30%  (p=0.000 n=9+10)
MapPutGrow/Int32/2048-16              128µs ± 0%      78µs ± 2%    -39.40%  (p=0.000 n=10+10)
MapPutGrow/Int32/4096-16              252µs ± 0%     178µs ± 2%    -29.59%  (p=0.000 n=10+10)
MapPutGrow/Int32/8192-16              506µs ± 1%     424µs ± 2%    -16.19%  (p=0.000 n=10+10)
MapPutGrow/Int32/65536-16            4.57ms ± 3%    3.82ms ± 2%    -16.27%  (p=0.000 n=10+10)
MapPutGrow/String/6-16               90.0ns ± 0%   187.7ns ± 2%   +108.57%  (p=0.000 n=10+10)
MapPutGrow/String/12-16               518ns ± 2%     513ns ± 2%       ~     (p=0.066 n=10+10)
MapPutGrow/String/18-16              1.18µs ± 0%    1.06µs ± 2%    -10.44%  (p=0.000 n=6+10)
MapPutGrow/String/24-16              1.41µs ± 1%    1.17µs ± 2%    -16.95%  (p=0.000 n=10+10)
MapPutGrow/String/30-16              2.57µs ± 1%    2.17µs ± 2%    -15.36%  (p=0.000 n=10+10)
MapPutGrow/String/64-16              5.80µs ± 1%    4.45µs ± 2%    -23.29%  (p=0.000 n=10+10)
MapPutGrow/String/128-16             11.5µs ± 1%     8.6µs ± 3%    -25.27%  (p=0.000 n=10+10)
MapPutGrow/String/256-16             22.9µs ± 1%    16.3µs ± 1%    -28.71%  (p=0.000 n=10+10)
MapPutGrow/String/512-16             46.1µs ± 1%    31.4µs ± 2%    -31.91%  (p=0.000 n=10+10)
MapPutGrow/String/1024-16            92.1µs ± 1%    62.5µs ± 2%    -32.18%  (p=0.000 n=10+10)
MapPutGrow/String/2048-16             185µs ± 1%     122µs ± 2%    -34.18%  (p=0.000 n=10+10)
MapPutGrow/String/4096-16             392µs ± 2%     266µs ± 2%    -32.21%  (p=0.000 n=10+10)
MapPutGrow/String/8192-16             923µs ± 1%     612µs ± 1%    -33.68%  (p=0.000 n=10+8)
MapPutGrow/String/65536-16           9.55ms ± 3%    6.64ms ± 5%    -30.48%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/6-16         85.4ns ± 0%   135.0ns ± 2%    +58.12%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/12-16         344ns ± 1%     217ns ± 1%    -36.85%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/18-16         553ns ± 0%     310ns ± 1%    -43.93%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/24-16         785ns ± 1%     389ns ± 2%    -50.46%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/30-16         950ns ± 1%     535ns ± 3%    -43.69%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/64-16        2.19µs ± 0%    1.05µs ± 2%    -52.14%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/128-16       4.21µs ± 0%    2.03µs ± 2%    -51.68%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/256-16       8.02µs ± 1%    3.91µs ± 3%    -51.22%  (p=0.000 n=9+10)
MapPutPreAllocate/Int64/512-16       16.0µs ± 1%     7.3µs ± 2%    -54.08%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/1024-16      31.9µs ± 1%    14.1µs ± 1%    -55.87%  (p=0.000 n=10+10)
MapPutPreAllocate/Int64/2048-16      64.0µs ± 1%    27.5µs ± 1%    -57.09%  (p=0.000 n=9+10)
MapPutPreAllocate/Int64/4096-16       131µs ± 0%      65µs ± 1%    -50.64%  (p=0.000 n=8+10)
MapPutPreAllocate/Int64/8192-16       272µs ± 0%     136µs ± 1%    -50.06%  (p=0.000 n=10+9)
MapPutPreAllocate/Int64/65536-16     2.57ms ± 1%    1.49ms ± 4%    -42.08%  (p=0.000 n=8+10)
MapPutPreAllocate/Int32/6-16         86.8ns ± 0%   134.7ns ± 2%    +55.15%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/12-16         313ns ± 0%     210ns ± 2%    -33.12%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/18-16         501ns ± 0%     288ns ± 2%    -42.63%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/24-16         720ns ± 0%     367ns ± 2%    -49.01%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/30-16         850ns ± 1%     481ns ± 2%    -43.42%  (p=0.000 n=9+10)
MapPutPreAllocate/Int32/64-16        1.94µs ± 1%    0.92µs ± 2%    -52.84%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/128-16       3.80µs ± 1%    1.78µs ± 2%    -53.22%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/256-16       7.54µs ± 0%    3.50µs ± 3%    -53.60%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/512-16       14.5µs ± 1%     6.9µs ± 1%    -52.57%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/1024-16      28.6µs ± 0%    13.2µs ± 1%    -53.69%  (p=0.000 n=10+9)
MapPutPreAllocate/Int32/2048-16      58.0µs ± 1%    25.7µs ± 2%    -55.71%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/4096-16       118µs ± 0%      61µs ± 1%    -48.36%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/8192-16       242µs ± 1%     126µs ± 2%    -47.80%  (p=0.000 n=10+10)
MapPutPreAllocate/Int32/65536-16     2.48ms ± 2%    1.20ms ± 6%    -51.51%  (p=0.000 n=10+10)
MapPutPreAllocate/String/6-16        92.4ns ± 0%   179.5ns ± 2%    +94.25%  (p=0.000 n=9+10)
MapPutPreAllocate/String/12-16        412ns ± 0%     298ns ± 2%    -27.54%  (p=0.000 n=10+10)
MapPutPreAllocate/String/18-16        697ns ± 0%     474ns ± 2%    -32.03%  (p=0.000 n=9+10)
MapPutPreAllocate/String/24-16        943ns ± 1%     568ns ± 2%    -39.80%  (p=0.000 n=10+10)
MapPutPreAllocate/String/30-16       1.23µs ± 1%    0.81µs ± 2%    -33.98%  (p=0.000 n=9+10)
MapPutPreAllocate/String/64-16       2.68µs ± 1%    1.61µs ± 2%    -39.90%  (p=0.000 n=10+10)
MapPutPreAllocate/String/128-16      5.14µs ± 1%    3.12µs ± 1%    -39.33%  (p=0.000 n=10+10)
MapPutPreAllocate/String/256-16      10.3µs ± 1%     5.8µs ± 2%    -43.45%  (p=0.000 n=10+10)
MapPutPreAllocate/String/512-16      20.7µs ± 1%    11.0µs ± 2%    -46.91%  (p=0.000 n=10+10)
MapPutPreAllocate/String/1024-16     42.1µs ± 1%    22.4µs ± 1%    -46.84%  (p=0.000 n=10+10)
MapPutPreAllocate/String/2048-16     84.3µs ± 1%    44.8µs ± 3%    -46.86%  (p=0.000 n=10+10)
MapPutPreAllocate/String/4096-16      177µs ± 1%      99µs ± 2%    -44.37%  (p=0.000 n=10+10)
MapPutPreAllocate/String/8192-16      378µs ± 1%     227µs ± 6%    -40.02%  (p=0.000 n=10+10)
MapPutPreAllocate/String/65536-16    3.99ms ± 3%    3.42ms ±16%    -14.35%  (p=0.000 n=10+10)
MapPutReuse/Int64/6-16               96.4ns ± 1%    81.1ns ± 0%    -15.87%  (p=0.000 n=10+8)
MapPutReuse/Int64/12-16               283ns ± 0%     196ns ± 0%    -30.72%  (p=0.000 n=10+8)
MapPutReuse/Int64/18-16               449ns ± 1%     234ns ±34%    -47.95%  (p=0.000 n=10+10)
MapPutReuse/Int64/24-16               678ns ± 1%     336ns ±13%    -50.42%  (p=0.000 n=9+8)
MapPutReuse/Int64/30-16               775ns ± 0%     354ns ± 1%    -54.29%  (p=0.000 n=10+9)
MapPutReuse/Int64/64-16              1.71µs ± 1%    0.73µs ± 4%    -57.15%  (p=0.000 n=10+9)
MapPutReuse/Int64/128-16             3.44µs ± 1%    1.48µs ± 2%    -57.17%  (p=0.000 n=10+8)
MapPutReuse/Int64/256-16             6.90µs ± 1%    2.86µs ± 2%    -58.56%  (p=0.000 n=10+8)
MapPutReuse/Int64/512-16             13.7µs ± 0%     5.7µs ± 3%    -58.74%  (p=0.000 n=10+10)
MapPutReuse/Int64/1024-16            27.4µs ± 0%    11.4µs ± 1%    -58.53%  (p=0.000 n=10+8)
MapPutReuse/Int64/2048-16            56.9µs ± 0%    23.9µs ± 1%    -58.01%  (p=0.000 n=10+10)
MapPutReuse/Int64/4096-16             117µs ± 1%      61µs ± 3%    -48.15%  (p=0.000 n=10+10)
MapPutReuse/Int64/8192-16             240µs ± 1%     121µs ± 1%    -49.48%  (p=0.000 n=10+10)
MapPutReuse/Int64/65536-16           2.39ms ± 1%    1.13ms ± 1%    -52.53%  (p=0.000 n=10+10)
MapPutReuse/Int32/6-16               98.3ns ± 0%    81.2ns ± 0%    -17.48%  (p=0.000 n=10+10)
MapPutReuse/Int32/12-16               281ns ± 0%     195ns ± 0%    -30.78%  (p=0.000 n=10+8)
MapPutReuse/Int32/18-16               456ns ± 1%     209ns ± 1%    -54.07%  (p=0.000 n=10+10)
MapPutReuse/Int32/24-16               680ns ± 1%     289ns ± 1%    -57.55%  (p=0.000 n=10+10)
MapPutReuse/Int32/30-16               791ns ± 1%     355ns ± 0%    -55.09%  (p=0.000 n=10+9)
MapPutReuse/Int32/64-16              1.72µs ± 1%    0.72µs ± 1%    -58.03%  (p=0.000 n=10+9)
MapPutReuse/Int32/128-16             3.52µs ± 0%    1.54µs ±16%    -56.31%  (p=0.000 n=10+8)
MapPutReuse/Int32/256-16             7.06µs ± 1%    2.81µs ± 0%    -60.18%  (p=0.000 n=9+8)
MapPutReuse/Int32/512-16             14.1µs ± 0%     5.6µs ± 1%    -60.14%  (p=0.000 n=10+9)
MapPutReuse/Int32/1024-16            28.0µs ± 0%    11.4µs ± 2%    -59.32%  (p=0.000 n=10+8)
MapPutReuse/Int32/2048-16            55.2µs ± 0%    23.0µs ± 1%    -58.40%  (p=0.000 n=10+10)
MapPutReuse/Int32/4096-16             115µs ± 0%      59µs ± 1%    -48.79%  (p=0.000 n=10+10)
MapPutReuse/Int32/8192-16             237µs ± 1%     120µs ± 2%    -49.26%  (p=0.000 n=10+10)
MapPutReuse/Int32/65536-16           2.14ms ± 1%    1.02ms ± 1%    -52.16%  (p=0.000 n=9+10)
MapPutReuse/String/6-16               108ns ± 0%     105ns ± 0%     -1.88%  (p=0.000 n=9+9)
MapPutReuse/String/12-16              315ns ± 0%     232ns ±25%    -26.45%  (p=0.000 n=10+10)
MapPutReuse/String/18-16              519ns ± 1%     301ns ±13%    -42.04%  (p=0.000 n=10+10)
MapPutReuse/String/24-16              771ns ± 0%     378ns ±14%    -51.01%  (p=0.000 n=9+9)
MapPutReuse/String/30-16              898ns ± 1%     460ns ± 1%    -48.80%  (p=0.000 n=10+9)
MapPutReuse/String/64-16             1.93µs ± 1%    0.95µs ± 2%    -50.83%  (p=0.000 n=10+9)
MapPutReuse/String/128-16            3.90µs ± 0%    1.94µs ± 5%    -50.36%  (p=0.000 n=10+9)
MapPutReuse/String/256-16            7.80µs ± 1%    3.99µs ± 5%    -48.87%  (p=0.000 n=10+10)
MapPutReuse/String/512-16            15.5µs ± 1%     7.7µs ± 0%    -50.51%  (p=0.000 n=10+7)
MapPutReuse/String/1024-16           32.6µs ± 1%    17.5µs ± 7%    -46.17%  (p=0.000 n=10+10)
MapPutReuse/String/2048-16           66.9µs ± 1%    33.9µs ± 1%    -49.35%  (p=0.000 n=10+10)
MapPutReuse/String/4096-16            136µs ± 2%      82µs ± 1%    -39.56%  (p=0.000 n=10+8)
MapPutReuse/String/8192-16            282µs ± 1%     163µs ± 1%    -42.19%  (p=0.000 n=10+10)
MapPutReuse/String/65536-16          3.12ms ± 2%    1.83ms ± 2%    -41.26%  (p=0.000 n=9+9)
MapPutDelete/Int64/6-16              27.0ns ± 1%    24.7ns ± 6%     -8.63%  (p=0.000 n=10+10)
MapPutDelete/Int64/12-16             29.0ns ± 6%    28.0ns ± 8%     -3.76%  (p=0.023 n=9+10)
MapPutDelete/Int64/18-16             28.2ns ± 5%    26.2ns ±10%     -7.24%  (p=0.011 n=9+10)
MapPutDelete/Int64/24-16             30.9ns ± 7%    27.9ns ± 6%     -9.81%  (p=0.000 n=10+9)
MapPutDelete/Int64/30-16             27.1ns ± 7%    26.6ns ±15%       ~     (p=0.393 n=10+10)
MapPutDelete/Int64/64-16             27.8ns ± 5%    29.3ns ±17%       ~     (p=0.353 n=10+10)
MapPutDelete/Int64/128-16            28.3ns ± 4%    32.6ns ±34%       ~     (p=0.190 n=10+10)
MapPutDelete/Int64/256-16            28.3ns ± 5%    32.0ns ±11%    +13.17%  (p=0.000 n=10+10)
MapPutDelete/Int64/512-16            28.2ns ± 2%    32.2ns ±14%    +14.01%  (p=0.000 n=10+10)
MapPutDelete/Int64/1024-16           34.5ns ± 2%    36.4ns ± 9%     +5.53%  (p=0.001 n=10+10)
MapPutDelete/Int64/2048-16           47.7ns ± 1%    39.3ns ± 9%    -17.66%  (p=0.000 n=10+10)
MapPutDelete/Int64/4096-16           53.4ns ± 1%    49.6ns ± 5%     -7.26%  (p=0.000 n=9+10)
MapPutDelete/Int64/8192-16           56.3ns ± 1%    52.7ns ± 4%     -6.48%  (p=0.000 n=10+8)
MapPutDelete/Int64/65536-16          70.3ns ± 2%    66.1ns ± 5%     -5.99%  (p=0.000 n=10+10)
MapPutDelete/Int32/6-16              27.2ns ± 0%    24.0ns ± 0%    -11.87%  (p=0.000 n=9+9)
MapPutDelete/Int32/12-16             27.9ns ± 3%    28.1ns ± 2%       ~     (p=0.340 n=9+9)
MapPutDelete/Int32/18-16             27.3ns ± 8%    26.4ns ± 9%       ~     (p=0.280 n=10+10)
MapPutDelete/Int32/24-16             29.9ns ±10%    27.7ns ± 5%     -7.48%  (p=0.000 n=10+9)
MapPutDelete/Int32/30-16             26.9ns ±14%    27.1ns ±13%       ~     (p=0.929 n=10+10)
MapPutDelete/Int32/64-16             26.6ns ± 4%    29.5ns ±18%       ~     (p=0.063 n=10+10)
MapPutDelete/Int32/128-16            26.9ns ± 2%    29.8ns ±20%       ~     (p=0.079 n=10+10)
MapPutDelete/Int32/256-16            26.7ns ± 2%    33.7ns ±12%    +26.59%  (p=0.000 n=10+10)
MapPutDelete/Int32/512-16            27.4ns ± 3%    33.0ns ±16%    +20.44%  (p=0.000 n=10+10)
MapPutDelete/Int32/1024-16           32.7ns ± 3%    37.4ns ± 9%    +14.34%  (p=0.000 n=10+10)
MapPutDelete/Int32/2048-16           44.8ns ± 2%    38.6ns ± 5%    -13.98%  (p=0.000 n=10+8)
MapPutDelete/Int32/4096-16           51.4ns ± 1%    48.0ns ± 3%     -6.77%  (p=0.000 n=10+10)
MapPutDelete/Int32/8192-16           54.3ns ± 1%    52.1ns ± 2%     -3.98%  (p=0.000 n=9+10)
MapPutDelete/Int32/65536-16          60.5ns ± 1%    58.9ns ± 1%     -2.66%  (p=0.000 n=10+10)
MapPutDelete/String/6-16             32.5ns ± 1%    26.5ns ± 0%    -18.47%  (p=0.000 n=10+9)
MapPutDelete/String/12-16            33.6ns ± 1%    36.2ns ± 9%     +7.88%  (p=0.005 n=8+9)
MapPutDelete/String/18-16            32.2ns ± 5%    36.8ns ±15%    +14.34%  (p=0.001 n=9+10)
MapPutDelete/String/24-16            34.9ns ±10%    37.2ns ± 6%     +6.54%  (p=0.004 n=10+9)
MapPutDelete/String/30-16            31.8ns ± 5%    33.6ns ±30%       ~     (p=0.780 n=9+10)
MapPutDelete/String/64-16            32.3ns ± 2%    37.5ns ±18%    +16.22%  (p=0.002 n=10+10)
MapPutDelete/String/128-16           32.4ns ± 2%    38.7ns ±16%    +19.48%  (p=0.000 n=10+10)
MapPutDelete/String/256-16           33.1ns ± 2%    42.0ns ±10%    +26.68%  (p=0.000 n=10+10)
MapPutDelete/String/512-16           34.0ns ± 4%    40.3ns ±16%    +18.32%  (p=0.000 n=10+9)
MapPutDelete/String/1024-16          49.0ns ± 2%    45.7ns ± 8%     -6.87%  (p=0.000 n=10+10)
MapPutDelete/String/2048-16          64.3ns ± 2%    49.2ns ± 7%    -23.40%  (p=0.000 n=10+10)
MapPutDelete/String/4096-16          70.5ns ± 1%    60.0ns ± 4%    -14.85%  (p=0.000 n=10+10)
MapPutDelete/String/8192-16          72.3ns ± 1%    61.5ns ± 1%    -14.92%  (p=0.000 n=9+8)
MapPutDelete/String/65536-16          119ns ± 3%     108ns ± 7%     -9.55%  (p=0.000 n=10+10)

On top of the base Swiss Tables design, swiss.Map adds an extendible hashing layer in order to enable incremental resizing of large maps which significantly reduces tail latency for Put operations in maps with hundreds of thousands of entries or more.

swiss.Map provides pseudo-randomized iteration (iteration order will change from one iteration to the next) and iteration stability akin to Go's builtin map if the map is mutated during iteration.

Caveats

  • The implementation currently requires a little endian CPU architecture. This is not a fundamental limitation of the implementation, merely a choice of expediency.
  • Go's builtin map has a fast-path for comparing strings that share their underlying storage. This fast-path is feasible because map[string]T is specialized for string keys which isn't currently possible with Go's generics.
  • Go's builtin map has a fast-path for maps with int32, int64, and string keys that fit in a single bucket (8 entries) which avoids performing hash(key) and simply linearly searches through the bucket. Similar to the above, this fast-path is feasible because the runtime can specialize the implementation on the key type.

TODO

  • Add support for SIMD searching on x86 and 8-byte Neon SIMD searching on arm64
    • This appears to be somewhat difficult. Naively implementing the match routines in assembly isn't workable as the function call overhead dominates the performance improvement from the SIMD comparisons. The Abseil implementation is leveraring gcc/llvm assembly intrinsics which are not currently available in Go. In order to take advantage of SIMD we'll have to write most/all of the probing loop in assembly.