Part 1 of this saga shipped a compare-and-swap loop that gave up after 100 tries. It can fail at most 64 times. What really loses an Add is Union, with no retry involved and nothing the race detector can see. With …
An atomic-first Go Bloom filter still tripped the race detector. A war story about the read that looked benign, and what the Go memory model has to say about it.
A line-by-line reading of avx2.s: runtime AVX2 detection, and hand-written Go assembly for population count, bitwise OR and AND, and clearing 32 bytes at a time.
Making the Bloom filter thread-safe cost 8–12x in throughput. The culprit was a heap allocation on every Add and Contains; the fix was a stack array for small hash counts.
Concurrent reads were panicking in a Go Bloom filter because Contains() quietly mutated shared scratchpad state. How the race was found, fixed, and what the fix cost.
A benchmark that measured fmt.Sprintf instead of the filter, several pprof sessions, one optimisation that made things worse, and the data-structure change that finally paid.