Huge news!Announcing our $20M Series A led by Andreessen Horowitz.Learn more
Log inDemoInstall

Package Overview
File Explorer

Package hashmap provides a lock-free and thread-safe HashMap.


Version published



Build status reference Go Report Card codecov


A Golang lock-free thread-safe HashMap optimized for fastest read access.

It is not a general-use HashMap and currently has slow write performance for write heavy uses.

The minimal supported Golang version is 1.19 as it makes use of Generics and the new atomic package helpers.


Example uint8 key map uses:

m := New[uint8, int]()
m.Set(1, 123)
value, ok := m.Get(1)

Example string key map uses:

m := New[string, int]()
m.Set("amount", 123)
value, ok := m.Get("amount")

Using the map to count URL requests:

m := New[string, *int64]()
var i int64
counter, _ := m.GetOrInsert("api/123", &i)
atomic.AddInt64(counter, 1) // increase counter
count := atomic.LoadInt64(counter) // read counter


Reading from the hash map for numeric key types in a thread-safe way is faster than reading from a standard Golang map in an unsafe way and four times faster than Golang's sync.Map:

BenchmarkReadHashMapUint-8                	 1774460	       677.3 ns/op
BenchmarkReadHaxMapUint-8                 	 1758708	       679.0 ns/op
BenchmarkReadGoMapUintUnsafe-8            	 1497732	       790.9 ns/op
BenchmarkReadGoMapUintMutex-8             	   41562	     28672 ns/op
BenchmarkReadGoSyncMapUint-8              	  454401	      2646 ns/op

Reading from the map while writes are happening:

BenchmarkReadHashMapWithWritesUint-8      	 1388560	       859.1 ns/op
BenchmarkReadHaxMapWithWritesUint-8       	 1306671	       914.5 ns/op
BenchmarkReadGoSyncMapWithWritesUint-8    	  335732	      3113 ns/op

Write performance without any concurrent reads:

BenchmarkWriteHashMapUint-8               	   54756	     21977 ns/op
BenchmarkWriteGoMapMutexUint-8            	   83907	     14827 ns/op
BenchmarkWriteGoSyncMapUint-8             	   16983	     70305 ns/op

The benchmarks were run with Golang 1.19.0 on Linux and AMD64 using make benchmark.

Technical details

  • Technical design decisions have been made based on benchmarks that are stored in an external repository: go-benchmark

  • The library uses a sorted linked list and a slice as an index into that list.

  • The Get() function contains helper functions that have been inlined manually until the Golang compiler will inline them automatically.

  • It optimizes the slice access by circumventing the Golang size check when reading from the slice. Once a slice is allocated, the size of it does not change. The library limits the index into the slice, therefore the Golang size check is obsolete. When the slice reaches a defined fill rate, a bigger slice is allocated and all keys are recalculated and transferred into the new slice.

  • For hashing, specialized xxhash implementations are used that match the size of the key type where available


Last updated on 03 Sep 2022

Did you know?

Socket installs a GitHub app to automatically flag issues on every pull request and report the health of your dependencies. Find out what is inside your node modules and prevent malicious activity before you update the dependencies.

SocketSocket SOC 2 Logo


  • Package Issues
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc