Skip to content

Instantly share code, notes, and snippets.

@mix3
Created May 15, 2014 08:32
Show Gist options
  • Save mix3/1b98ca337556fcc643ad to your computer and use it in GitHub Desktop.
Save mix3/1b98ca337556fcc643ad to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"runtime"
"sync"
"testing"
)
type ChMutex struct {
wait chan int
}
func (m *ChMutex) Lock() {
if m.wait == nil {
m.wait = make(chan int, 1)
m.wait <- 1
}
<-m.wait
}
func (m *ChMutex) Unlock() {
if m.wait == nil {
panic("until locked")
}
m.wait <- 1
}
type ICounter interface {
Incr()
Count() int
}
type Counter struct {
count int
}
func (c *Counter) Incr() {
c.count++
}
func (c *Counter) Count() int {
return c.count
}
type MutexCounter struct {
Counter
sync.Mutex
}
func (c *MutexCounter) Incr() {
c.Mutex.Lock()
defer c.Mutex.Unlock()
c.Counter.Incr()
}
type ChMutexCounter struct {
Counter
ChMutex
}
func (c *ChMutexCounter) Incr() {
c.ChMutex.Lock()
defer c.ChMutex.Unlock()
c.Counter.Incr()
}
func incr(procs, maxNum int, c ICounter) {
runtime.GOMAXPROCS(procs)
wait := make(chan int)
go func() {
for i := 0; i < maxNum; i++ {
c.Incr()
}
wait <- 1
}()
go func() {
for i := 0; i < maxNum; i++ {
c.Incr()
}
wait <- 1
}()
<-wait
<-wait
fmt.Printf("GOMAXPROCS=%d expect=%d num=%d\n", procs, maxNum*2, c.Count())
}
func BenchmarkCounterProcs1(b *testing.B) {
incr(1, b.N, &Counter{0})
}
func BenchmarkCounterProcs2(b *testing.B) {
incr(2, b.N, &Counter{0})
}
func BenchmarkMutexCounterProcs1(b *testing.B) {
incr(1, b.N, &MutexCounter{Counter{0}, sync.Mutex{}})
}
func BenchmarkMutexCounterProcs2(b *testing.B) {
incr(2, b.N, &MutexCounter{Counter{0}, sync.Mutex{}})
}
func BenchmarkChMutexCounterProcs1(b *testing.B) {
incr(1, b.N, &ChMutexCounter{Counter{0}, ChMutex{}})
}
func BenchmarkChMutexCounterProcs2(b *testing.B) {
incr(2, b.N, &ChMutexCounter{Counter{0}, ChMutex{}})
}
@mix3
Copy link
Author

mix3 commented May 15, 2014

$ go test -bench .

testing: warning: no tests to run
PASS
BenchmarkCounterProcs1  GOMAXPROCS=1 expect=2 num=2
GOMAXPROCS=1 expect=200 num=200
GOMAXPROCS=1 expect=20000 num=20000
GOMAXPROCS=1 expect=2000000 num=2000000
GOMAXPROCS=1 expect=200000000 num=200000000
GOMAXPROCS=1 expect=1000000000 num=1000000000
500000000            4.94 ns/op
BenchmarkCounterProcs2  GOMAXPROCS=2 expect=2 num=2
GOMAXPROCS=2 expect=200 num=200
GOMAXPROCS=2 expect=20000 num=12125
GOMAXPROCS=2 expect=2000000 num=1159723
GOMAXPROCS=2 expect=200000000 num=122849777
100000000           10.1 ns/op
testing: BenchmarkCounterProcs2 left GOMAXPROCS set to 2
BenchmarkMutexCounterProcs1 GOMAXPROCS=1 expect=2 num=2
GOMAXPROCS=1 expect=200 num=200
GOMAXPROCS=1 expect=20000 num=20000
GOMAXPROCS=1 expect=2000000 num=2000000
GOMAXPROCS=1 expect=20000000 num=20000000
10000000           210 ns/op
BenchmarkMutexCounterProcs2 GOMAXPROCS=2 expect=2 num=2
GOMAXPROCS=2 expect=200 num=200
GOMAXPROCS=2 expect=20000 num=20000
GOMAXPROCS=2 expect=2000000 num=2000000
GOMAXPROCS=2 expect=10000000 num=10000000
 5000000           566 ns/op
testing: BenchmarkMutexCounterProcs2 left GOMAXPROCS set to 2
BenchmarkChMutexCounterProcs1   GOMAXPROCS=1 expect=2 num=2
GOMAXPROCS=1 expect=200 num=200
GOMAXPROCS=1 expect=20000 num=20000
GOMAXPROCS=1 expect=2000000 num=2000000
GOMAXPROCS=1 expect=20000000 num=20000000
10000000           284 ns/op
BenchmarkChMutexCounterProcs2   GOMAXPROCS=2 expect=2 num=2
GOMAXPROCS=2 expect=200 num=200
GOMAXPROCS=2 expect=20000 num=20000
GOMAXPROCS=2 expect=2000000 num=2000000
GOMAXPROCS=2 expect=4000000 num=4000000
 2000000           885 ns/op
testing: BenchmarkChMutexCounterProcs2 left GOMAXPROCS set to 2
ok

@mix3
Copy link
Author

mix3 commented May 15, 2014

$ go test -bench .

testing: warning: no tests to run
PASS
BenchmarkCounterProcs1  GOMAXPROCS=1 expect=2 num=2
GOMAXPROCS=1 expect=200 num=200
GOMAXPROCS=1 expect=20000 num=20000
GOMAXPROCS=1 expect=2000000 num=2000000
GOMAXPROCS=1 expect=200000000 num=200000000
GOMAXPROCS=1 expect=1000000000 num=1000000000
500000000            5.58 ns/op
BenchmarkCounterProcs2  GOMAXPROCS=2 expect=2 num=2
GOMAXPROCS=2 expect=200 num=141
GOMAXPROCS=2 expect=20000 num=10808
GOMAXPROCS=2 expect=2000000 num=1161053
GOMAXPROCS=2 expect=200000000 num=125299244
GOMAXPROCS=2 expect=400000000 num=241509326
200000000            9.58 ns/op
testing: BenchmarkCounterProcs2 left GOMAXPROCS set to 2
BenchmarkMutexCounterProcs1 GOMAXPROCS=1 expect=2 num=2
GOMAXPROCS=1 expect=200 num=200
GOMAXPROCS=1 expect=20000 num=20000
GOMAXPROCS=1 expect=2000000 num=2000000
GOMAXPROCS=1 expect=20000000 num=20000000
10000000           208 ns/op
BenchmarkMutexCounterProcs2 GOMAXPROCS=2 expect=2 num=2
GOMAXPROCS=2 expect=200 num=200
GOMAXPROCS=2 expect=20000 num=20000
GOMAXPROCS=2 expect=2000000 num=2000000
GOMAXPROCS=2 expect=10000000 num=10000000
 5000000           635 ns/op
testing: BenchmarkMutexCounterProcs2 left GOMAXPROCS set to 2
BenchmarkChMutexCounterProcs1   GOMAXPROCS=1 expect=2 num=2
GOMAXPROCS=1 expect=200 num=200
GOMAXPROCS=1 expect=20000 num=20000
GOMAXPROCS=1 expect=2000000 num=2000000
GOMAXPROCS=1 expect=20000000 num=20000000
10000000           288 ns/op
BenchmarkChMutexCounterProcs2   GOMAXPROCS=2 expect=2 num=2
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
...

goroutine 62 [chan receive]:
...

goroutine 65 [chan send]:
...
exit status 2
FAIL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment