8 comments

  • tl2do 4 hours ago
    I ran benchmarks comparing xsync.Map's memory allocation against orcaman/concurrent-map.

    Pure overwrite workload (pre-allocated values): xsync.Map: 24 B/op 1 alloc/op 31.89 ns/op orcaman/concurrent-map: 0 B/op 0 alloc/op 70.72 ns/op

    Real-world mixed (80% overwrites, 20% new): xsync.Map: 57 B/op 2 allocs/op 218.1 ns/op orcaman/concurrent-map: 63 B/op 3 allocs/op 283.1 ns/op

    Go maps reuse memory on overwrites, which is why orcaman achieves 0 B/op for pure updates. xsync's custom bucket structure allocates 24 B/op per write even when overwriting existing keys.

    At 1M writes/second with 90% overwrites: xsync allocates ~27 MB/s, orcaman ~6 MB/s. The trade is 24 bytes/op for 2x speed under contention. Whether this matters depends on whether your bottleneck is CPU or memory allocation.

    Benchmark code: standard Go testing framework, 8 workers, 100k keys.

    • hinkley 1 hour ago
      How does reuse avoid false sharing between cores? Since this is concurrent hashmap we are talking about.
  • withinboredom 5 hours ago
    Looks good! There's an important thing missing from the benchmarks though:

    - cpu usage under concurrency: many of these spin-lock or use atomics, which can use up to 100% cpu time just spinning.

    - latency under concurrency: atomics cause cache-line bouncing which kills latency, especially p99 latency

  • kgeist 1 hour ago
    Orcaman is a very straightforward implementation (just sharded RW locks and backing maps), but it limits the number of shards to a fixed 32. I wonder what the benchmarks would look like if the shard count were increased to 64, 128, etc.
  • mappu 2 hours ago
    A few release cycles back, Swiss Maps became popular (i think, particular thanks to CockroachDB) as a replacement for standard Go map[K]V.

    Later, Go's stdlib map implementation was updated to use Swiss Maps internally and everyone benefited.

    Do you think the xsync.Map could be considered for upstreaming? Especially if it outperforms sync.Map at all the same use cases.

  • eatonphil 5 hours ago
    Will we also eventually get a generic sync.Map?
    • darkr 1 hour ago
      It’d be nice to have in stdlib, but it’s pretty trivial to write a generic wrapper for it
    • jeffbee 5 hours ago
      Almost certainly, since the internal HashTrieMap is already generic. But for now this author's package stands in nicely.
  • candiddevmike 4 hours ago
    Idk why but I tend to shy away from non std libs that use unsafe (like xsync). I'm sure the code is fine, but I'd rather take the performance hit I guess.
  • vanderZwan 5 hours ago
    I don't write Go but respect to the author for trying to list trade-off considerations for each of the implementations tested, and not just proclaim their library the overal winner.