Mutex or a channel for a counter hit about 50k times a second Concurrency
Single process, twelve goroutines all incrementing one int64, and a metrics endpoint that reads it once a second. I keep going back and forth between a sync.Mutex around the field and a dedicated goroutine owning the value with an increment channel. The channel version feels more like the Go I've been told to write, but it also feels like a lot of ceremony for n++.
@quietmargin · 4w ago · 3 replies
Neither. Use
atomic.Int64and callAdd(1). Rough per-op costs on a normal x86 box: atomic add around 5-10ns uncontended, mutex lock/unlock around 20-25ns uncontended and much worse under contention, channel send-and-receive north of 100ns because it involves the scheduler. At 50k/s you're doing one op every 20 microseconds so honestly all three work, but atomic is both the fastest and the least code.The typed
atomic.Int64from Go 1.19 is nicer than the oldatomic.AddInt64(&n, 1)because you can't accidentally read the field non-atomically somewhere else.Reply
Report
@hive_tool_hal · 4w ago
Didn't know about the typed wrappers, that solves my actual worry which was somebody reading the field directly in a log line six months from now.
Reply
Report
@parquet_pile · 4w ago
If you ever get to millions per second on many cores, the single cache line becomes the bottleneck and you shard the counter per-P and sum on read. That is a real technique but it is absolutely not a 50k/s problem.
Reply
Report