DEV Community

YooWaan
YooWaan

Posted on

2 2

Golang atomic.AddInt64 not fast ////

I benchmarked golang simple countup of not fixed code, mutex, atomic.AddInt64 or atomic.Value on goroutine.

Result

fastest result: atomic.Value > mutex > not fixed code > atomic.AddInt64

One time result

$ go test -bench .
goos: linux
goarch: amd64
BenchmarkInc_Countup-4               2000000           957 ns/op
--- BENCH: BenchmarkInc_Countup-4
    acounter_test.go:13: 1 -> 1
    acounter_test.go:13: 100 -> 100
    acounter_test.go:13: 10000 -> 9752
    acounter_test.go:13: 1000000 -> 982973
    acounter_test.go:13: 2000000 -> 1962072
BenchmarkLock_Countup-4              2000000           936 ns/op
--- BENCH: BenchmarkLock_Countup-4
    acounter_test.go:20: 1 -> 1
    acounter_test.go:20: 100 -> 100
    acounter_test.go:20: 10000 -> 10000
    acounter_test.go:20: 1000000 -> 1000000
    acounter_test.go:20: 2000000 -> 2000000
BenchmarkAtomic_Countup-4            2000000           943 ns/op
--- BENCH: BenchmarkAtomic_Countup-4
    acounter_test.go:27: 1 -> 1
    acounter_test.go:27: 100 -> 100
    acounter_test.go:27: 10000 -> 10000
    acounter_test.go:27: 1000000 -> 1000000
    acounter_test.go:27: 2000000 -> 2000000
BenchmarkAtomicValue_Countup-4       2000000           904 ns/op
--- BENCH: BenchmarkAtomicValue_Countup-4
    acounter_test.go:36: 1 -> 1
    acounter_test.go:36: 100 -> 54
    acounter_test.go:36: 10000 -> 7125
    acounter_test.go:36: 1000000 -> 791697
    acounter_test.go:36: 2000000 -> 1586774
PASS

Three times result

$ for i in $(seq 1 3); do go test -bench . | grep 'ns/op'; done
BenchmarkInc_Countup-4               2000000           998 ns/op
BenchmarkLock_Countup-4              2000000           986 ns/op
BenchmarkAtomic_Countup-4            2000000          1130 ns/op
BenchmarkAtomicValue_Countup-4       2000000           987 ns/op
BenchmarkInc_Countup-4               2000000           989 ns/op
BenchmarkLock_Countup-4              1000000          1113 ns/op
BenchmarkAtomic_Countup-4            1000000          1010 ns/op
BenchmarkAtomicValue_Countup-4       2000000          1013 ns/op
BenchmarkInc_Countup-4               1000000          1018 ns/op
BenchmarkLock_Countup-4              1000000          1311 ns/op
BenchmarkAtomic_Countup-4            1000000          1051 ns/op
BenchmarkAtomicValue_Countup-4       1000000          1125 ns/op

Code

package main
import (
"sync"
"sync/atomic"
)
var mutex sync.Mutex
var value atomic.Value
type Counter int64
func (c *Counter) Inc() {
*c++
}
func (c *Counter) AtomicInc() {
atomic.AddInt64((*int64)(c), 1)
}
func (c *Counter) LockInc() {
mutex.Lock()
defer mutex.Unlock()
*c++
}
func incValue() {
cnt := value.Load().(Counter)
cnt++
value.Store(cnt)
}
func countup(inc func(), n int) {
var wg sync.WaitGroup
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
inc()
}()
}
wg.Wait()
}
view raw main.go hosted with ❤ by GitHub

Benchmark Code

package main
// go test -bench . | grep 'ns/op'
import (
"testing"
)
func BenchmarkInc_Countup(b *testing.B) {
var cnt Counter
b.ResetTimer()
countup(cnt.Inc, b.N)
b.Logf("%d -> %d", b.N, cnt)
}
func BenchmarkLock_Countup(b *testing.B) {
var cnt Counter
b.ResetTimer()
countup(cnt.LockInc, b.N)
b.Logf("%d -> %d", b.N, cnt)
}
func BenchmarkAtomic_Countup(b *testing.B) {
var cnt Counter
b.ResetTimer()
countup(cnt.AtomicInc, b.N)
b.Logf("%d -> %d", b.N, cnt)
}
func BenchmarkAtomicValue_Countup(b *testing.B) {
var cnt Counter
value.Store(cnt)
b.ResetTimer()
countup(incValue, b.N)
cnt = value.Load().(Counter)
b.Logf("%d -> %d", b.N, cnt)
}
view raw main_test.go hosted with ❤ by GitHub

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (1)

Collapse
 
yanmhlv profile image
Yan Mihailov • Edited

Hi YooWaan! You can replace bash command to go-test arguments
instead of using this:

$ for i in $(seq 1 3); do go test -bench . | grep 'ns/op'; done
Enter fullscreen mode Exit fullscreen mode

you can use this:

go test \
    -v \
    -benchtime=10s \
    -benchmem \
    -count=5 \
    -bench=. \
    ./...
Enter fullscreen mode Exit fullscreen mode

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay