Performance optimization: xsync.Map bucket alignment fix
mainThe xsync.Map implementation includes a bucket-alignment fix that addresses a false sharing issue occurring in specific map sizes.
The Problem: False Sharing
In Go, for allocations in the [16, 512) byte range, the allocator prefixes the allocation with an 8-byte malloc header. This causes the slice base to sit at offset 8 (mod 64) instead of 0. In the original field order, the mu (mutex) field of bucket[i] would share a cache line with the hot read fields of bucket[i+1]. Consequently, every write operation (Store/Delete) on bucket[i] would invalidate the cache line for concurrent readers of bucket[i+1].
The Fix
The fields in the bucket struct were reordered so that mu precedes next. This ensures that frequent lock writes stay within the bucket's primary cache line, while the next pointer (which is only written during overflow chain growth) occupies the offset that shares a cache line with the next bucket.
Performance Impact
The fix provides significant performance gains for maps with 64 to 256 buckets (the default size and intermediate growth stages) without any API changes or memory overhead:
- Write-only workloads: 15–26% faster.
- Mixed workloads (e.g., 90% Load / 10% Store): 11–14% faster.
For maps with $\ge 512$ buckets, the allocation uses the large-object path (page-aligned), so the performance impact is negligible/zero.