Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Benchmarking Go Mutex overhead
package main
import (
"fmt"
"sync"
)
type unlocked struct {
i int
}
type locked struct {
i int
l sync.Mutex
}
func (c *unlocked) add() {
c.i++
}
func (c *locked) add() {
c.l.Lock()
defer c.l.Unlock()
c.i++
}
func main() {
fmt.Println("ok")
}
package main
import "testing"
func TestLocked_add(t *testing.T) {
c := locked{}
c.add()
if c.i != 1 {
t.Errorf("Expected 1 but got %d", c.i)
}
}
func BenchmarkLocked_add(t *testing.B) {
c := locked{}
for i := 0; i < t.N; i++ {
c.add()
}
if c.i != t.N {
t.Errorf("Expected %d, but got %d", t.N, c.i)
}
}
func TestUnlocked_add(t *testing.T) {
c := unlocked{}
c.add()
if c.i != 1 {
t.Errorf("Expected 1 but got %d", c.i)
}
}
func BenchmarkUnlocked_add(t *testing.B) {
c := unlocked{}
for i := 0; i < t.N; i++ {
c.add()
}
if c.i != t.N {
t.Errorf("Expected %d, but got %d", t.N, c.i)
}
}
$ go test -v -bench .
=== RUN TestLocked_add
--- PASS: TestLocked_add (0.00s)
=== RUN TestUnlocked_add
--- PASS: TestUnlocked_add (0.00s)
PASS
BenchmarkLocked_add 10000000 143 ns/op
BenchmarkUnlocked_add 1000000000 2.41 ns/op
ok _/home/hippo/test/mutex-bench 4.226s
@pascaldekloe

This comment has been minimized.

Copy link

commented Jan 3, 2019

go version go1.11.2 darwin/amd64

BenchmarkLocked_add-12      	30000000	        48.2 ns/op
BenchmarkUnlocked_add-12    	2000000000	         1.55 ns/op

Most of the slowdown comes from defer. When rewritten as

func (c *locked) add() {
	c.l.Lock()
	c.i++
	c.l.Unlock()
}

… then the numbers go down to:

BenchmarkLocked_add-12      	100000000	        19.4 ns/op
BenchmarkUnlocked_add-12    	2000000000	         1.55 ns/op
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.