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 Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

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

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay