Created
May 15, 2014 08:32
-
-
Save mix3/1b98ca337556fcc643ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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{}}) | |
} |
$ 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
$ go test -bench .