Skip to content

Instantly share code, notes, and snippets.

@zhenjl
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhenjl/15c87d9be571cbc83fcf to your computer and use it in GitHub Desktop.
Save zhenjl/15c87d9be571cbc83fcf to your computer and use it in GitHub Desktop.
A quick test of mutex vs CAS, using 1 or more goroutines and 1 or more CPU cores
// Results are in
// https://docs.google.com/spreadsheets/d/1R-KVBfKxM3KL2G4AuPtxr4SS_1iQYfrPTo0r5EZOFXs/pubhtml
package mutexvscas
import (
"testing"
"sync"
"log"
"time"
"sync/atomic"
)
type seq struct {
c0, c1, c2, c3, c4, c5, c6, c7 uint64
}
func Test1GoroutineNoLock(t *testing.T) {
c := seq{}
now := time.Now()
for c.c7 = 0; c.c7 < 500000000; c.c7++ {
}
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test1GoroutineNoLock", since, c.c7)
}
func Test1GoroutineWithLock(t *testing.T) {
c := seq{}
var mu sync.Mutex
now := time.Now()
for c.c7 = 0; c.c7 < 500000000; {
mu.Lock()
c.c7++
mu.Unlock()
}
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test1GoroutineWithLock", since, c.c7)
}
func Test2GoroutinesWithLock(t *testing.T) {
c := seq{}
var mu sync.Mutex
var wg sync.WaitGroup
now := time.Now()
wg.Add(2)
go func() {
for i := 0; i < 250000000; i++ {
mu.Lock()
c.c7++
mu.Unlock()
}
wg.Done()
}()
go func() {
for i := 0; i < 250000000; i++ {
mu.Lock()
c.c7++
mu.Unlock()
}
wg.Done()
}()
wg.Wait()
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test2GoroutinesWithLock", since, c.c7)
}
func Test100GoroutinesWithLock(t *testing.T) {
c := seq{}
var mu sync.Mutex
var wg sync.WaitGroup
now := time.Now()
wg.Add(100)
for r := 0; r < 100; r++ {
go func() {
for i := 0; i < 5000000; i++ {
mu.Lock()
c.c7++
mu.Unlock()
}
wg.Done()
}()
}
wg.Wait()
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test100GoroutinesWithLock", since, c.c7)
}
func Test1GoroutinewithCAS(t *testing.T) {
c := seq{}
now := time.Now()
for c.c7 = 0; c.c7 < 500000000; {
atomic.AddUint64(&(c.c7), 1)
}
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test1GoroutinewithCAS", since, c.c7)
}
func Test2GoroutinesWithCAS(t *testing.T) {
c := seq{}
var wg sync.WaitGroup
now := time.Now()
wg.Add(2)
go func() {
for c.c7 < 500000000 {
atomic.AddUint64(&(c.c7), 1)
}
wg.Done()
}()
go func() {
for c.c7 < 500000000 {
atomic.AddUint64(&(c.c7), 1)
}
wg.Done()
}()
wg.Wait()
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test2GoroutinesWithCAS", since, c.c7)
}
func Test1000GoroutinesWithCAS(t *testing.T) {
c := seq{}
var wg sync.WaitGroup
now := time.Now()
wg.Add(1000)
for r := 0; r < 1000; r++ {
go func() {
for c.c7 < 500000000 {
atomic.AddUint64(&(c.c7), 1)
}
wg.Done()
}()
}
wg.Wait()
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test1000GoroutinesWithCAS", since, c.c7)
}
func Test100000GoroutinesWithCAS(t *testing.T) {
c := seq{}
var wg sync.WaitGroup
now := time.Now()
wg.Add(100000)
for r := 0; r < 100000; r++ {
go func() {
for c.c7 < 500000000 {
atomic.AddUint64(&(c.c7), 1)
}
wg.Done()
}()
}
wg.Wait()
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test100000GoroutinesWithCAS", since, c.c7)
}
func Test1000000GoroutinesWithCAS(t *testing.T) {
c := seq{}
var wg sync.WaitGroup
now := time.Now()
wg.Add(1000000)
for r := 0; r < 1000000; r++ {
go func() {
for c.c7 < 500000000 {
atomic.AddUint64(&(c.c7), 1)
}
wg.Done()
}()
}
wg.Wait()
since := time.Since(now).Nanoseconds()
log.Printf("%28s: %11d %d", "Test1000000GoroutinesWithCAS", since, c.c7)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment