Releases: alphadose/haxmap
Performance improvement and fix 32-bit compatibility
Notes
- Hashing performance improvement by type-casting keys to arrays instead of slices as seen in this commit eee8abe
- Fixed tests for 32 bit platforms (tested on my raspberry pi running 32 bit raspian OS)
- Make map growth policy synchronous
Benchmarks
Benchmarks were performed against golang sync.Map and cornelk-hashmap-v1.0.6 for sample 20 cases
- Concurrent Reads Only
name time/op
HaxMapReadsOnly-8 8.75µs ± 9%
GoSyncMapReadsOnly-8 22.0µs ±11%
CornelkMapReadsOnly-8 9.20µs ±10%
- Concurrent Reads with Writes
name time/op
HaxMapReadsWithWrites-8 10.0µs ± 9%
GoSyncMapReadsWithWrites-8 24.8µs ±11%
CornelkMapReadsWithWrites-8 10.5µs ± 9%
name alloc/op
HaxMapReadsWithWrites-8 1.29kB ± 6%
GoSyncMapReadsWithWrites-8 6.20kB ± 5%
CornelkMapReadsWithWrites-8 1.59kB ±10%
name allocs/op
HaxMapReadsWithWrites-8 161 ± 4%
GoSyncMapReadsWithWrites-8 574 ± 5%
CornelkMapReadsWithWrites-8 198 ±10%
Hashing performance improvement
Notes
Performance gain obtained by inlining hash function assignments
Benchmarks
Benchmarks were performed against golang sync.Map and the latest cornelk-hashmap
All results were computed from benchstat of 20 runs (code available here)
- Concurrent Reads Only
name time/op
HaxMapReadsOnly-8 9.18µs ±12%
GoSyncMapReadsOnly-8 22.5µs ± 5%
CornelkMapReadsOnly-8 10.4µs ± 4%
name alloc/op
HaxMapReadsOnly-8 0.00B
GoSyncMapReadsOnly-8 0.00B
CornelkMapReadsOnly-8 0.00B
name allocs/op
HaxMapReadsOnly-8 0.00
GoSyncMapReadsOnly-8 0.00
CornelkMapReadsOnly-8 0.00
- Concurrent Reads with Writes
name time/op
HaxMapReadsWithWrites-8 10.5µs ± 7%
GoSyncMapReadsWithWrites-8 25.6µs ± 7%
CornelkMapReadsWithWrites-8 12.3µs ± 6%
name alloc/op
HaxMapReadsWithWrites-8 1.28kB ± 5%
GoSyncMapReadsWithWrites-8 6.23kB ± 6%
CornelkMapReadsWithWrites-8 5.89kB ± 7%
name allocs/op
HaxMapReadsWithWrites-8 159 ± 5%
GoSyncMapReadsWithWrites-8 577 ± 6%
CornelkMapReadsWithWrites-8 210 ± 8%
From the above results it is evident that haxmap
takes the least time, memory and allocations in all cases
Improve hashing performance
Notes
- Improved hashing performance leading to greater efficiency overall
- Fixed cases when hash key is 0 valued, now tests like the case below will no longer fail
func TestHash0Collision(t *testing.T) {
m := haxmap.New[string, int]()
staticHasher := func(key string) uintptr {
return 0
}
m.SetHasher(staticHasher)
m.Set("1", 1)
m.Set("2", 2)
_, ok := m.Get("1")
if !ok {
t.Error("1 not found")
}
_, ok = m.Get("2")
if !ok {
t.Error("2 not found")
}
}
Benchmarks
Benchmarks were performed against golang sync.Map and the latest cornelk-hashmap
All results were computed from benchstat of 20 runs (code available here)
- Concurrent Reads Only
name time/op
HaxMapReadsOnly-8 9.90µs ±13%
GoSyncMapReadsOnly-8 22.2µs ±14%
CornelkMapReadsOnly-8 10.4µs ±16%
name alloc/op
HaxMapReadsOnly-8 0.00B
GoSyncMapReadsOnly-8 0.00B
CornelkMapReadsOnly-8 0.00B
name allocs/op
HaxMapReadsOnly-8 0.00
GoSyncMapReadsOnly-8 0.00
CornelkMapReadsOnly-8 0.00
- Concurrent Reads with Writes
name time/op
HaxMapReadsWithWrites-8 11.2µs ±16%
GoSyncMapReadsWithWrites-8 25.6µs ±14%
CornelkMapReadsWithWrites-8 12.1µs ±12%
name alloc/op
HaxMapReadsWithWrites-8 1.35kB ± 8%
GoSyncMapReadsWithWrites-8 6.07kB ± 8%
CornelkMapReadsWithWrites-8 5.80kB ±10%
name allocs/op
HaxMapReadsWithWrites-8 168 ± 8%
GoSyncMapReadsWithWrites-8 562 ± 8%
CornelkMapReadsWithWrites-8 207 ±10%
From the above results it is evident that haxmap
takes the least time, memory and allocations in all cases
Performance++
- Huge performance gain obtained by switching bucket implementation to Harris lock-free list followed by additional optimizations from this paper
- Fixed issue #54 from cornelk-hashmap which caused data loss on concurrent writes during map resize operations
- Added support for 32-bit systems and more map key types
Benchmarks
Benchmarks were performed against golang sync.Map and the latest generics-enabled cornelk-hashmap
All results were computed from benchstat of 20 runs (code available here)
- Concurrent Reads Only
name time/op
HaxMapReadsOnly-8 10.9µs ±11%
GoSyncMapReadsOnly-8 23.0µs ± 7%
CornelkMapReadsOnly-8 12.3µs ±11%
name alloc/op
HaxMapReadsOnly-8 0.00B
GoSyncMapReadsOnly-8 0.00B
CornelkMapReadsOnly-8 0.00B
name allocs/op
HaxMapReadsOnly-8 0.00
GoSyncMapReadsOnly-8 0.00
CornelkMapReadsOnly-8 0.00
- Concurrent Reads with Writes
name time/op
HaxMapReadsWithWrites-8 12.6µs ±11%
GoSyncMapReadsWithWrites-8 25.6µs ±10%
CornelkMapReadsWithWrites-8 14.3µs ±13%
name alloc/op
HaxMapReadsWithWrites-8 1.46kB ± 3%
GoSyncMapReadsWithWrites-8 6.19kB ± 6%
CornelkMapReadsWithWrites-8 6.70kB ± 9%
name allocs/op
HaxMapReadsOnly-8 0.00
HaxMapReadsWithWrites-8 183 ± 3%
GoSyncMapReadsOnly-8 0.00
GoSyncMapReadsWithWrites-8 573 ± 7%
CornelkMapReadsOnly-8 0.00
CornelkMapReadsWithWrites-8 239 ± 9%
From the above results it is evident that haxmap
takes the least time, memory and allocations in all cases