Last active
March 25, 2021 22:17
-
-
Save dariodip/f289918b9f750b10ec962cd8ff2ae0c6 to your computer and use it in GitHub Desktop.
False Sharing in Go
This file contains 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
type Counter interface { | |
Increment() | |
} |
This file contains 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
const NCPU = 4 | |
const INCREMENT_TIME = 10000 | |
func testIncrementAll(c Counter) { | |
wg := sync.WaitGroup{} | |
wg.Add(NCPU) | |
for cpu := 0; cpu < NCPU; cpu++ { | |
go func(i int) { | |
for j := 0; j < INCREMENT_TIME; j++ { | |
c.Increment() | |
} | |
wg.Done() | |
}(cpu) | |
} | |
wg.Wait() | |
} | |
func BenchmarkNoPad(b *testing.B) { | |
counter := &NotPaddedCounter{} | |
b.ResetTimer() | |
testIncrementAll(counter) | |
} | |
func BenchmarkPad(b *testing.B) { | |
counter := &PaddedCounter{} | |
b.ResetTimer() | |
testIncrementAll(counter) | |
} |
This file contains 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
func incrementPos8(a *[]int8, pos int) { | |
(*a)[pos]++ | |
} | |
func incrementPos16(a *[]int16, pos int) { | |
(*a)[pos]++ | |
} | |
func incrementPos32(a *[]int32, pos int) { | |
(*a)[pos]++ | |
} | |
func incrementPos64(a *[]int64, pos int) { | |
(*a)[pos]++ | |
} |
This file contains 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 ( | |
"sync" | |
"testing" | |
) | |
const CPU_COUNT = 4 | |
const ADD_TIMES = 10000 | |
func BenchmarkFalseSharing8(b *testing.B) { | |
a := make([]int8, 4) | |
for n := 0; n < b.N*ADD_TIMES; n++ { | |
var wg sync.WaitGroup | |
for i := 0; i < CPU_COUNT; i++ { | |
wg.Add(1) | |
go func(_i int) { | |
for j := 0; j <= ADD_TIMES; j++ { | |
incrementPos8(&a, _i) | |
} | |
wg.Done() | |
}(i) | |
} | |
wg.Wait() | |
} | |
} | |
func BenchmarkFalseSharing16(b *testing.B) { | |
a := make([]int16, 4) | |
for n := 0; n < b.N*ADD_TIMES; n++ { | |
var wg sync.WaitGroup | |
for i := 0; i < CPU_COUNT; i++ { | |
wg.Add(1) | |
go func(_i int) { | |
for j := 0; j <= ADD_TIMES; j++ { | |
incrementPos16(&a, _i) | |
} | |
wg.Done() | |
}(i) | |
} | |
wg.Wait() | |
} | |
} | |
func BenchmarkFalseSharing32(b *testing.B) { | |
a := make([]int32, 4) | |
for n := 0; n < b.N*ADD_TIMES; n++ { | |
var wg sync.WaitGroup | |
for i := 0; i < CPU_COUNT; i++ { | |
wg.Add(1) | |
go func(_i int) { | |
for j := 0; j <= ADD_TIMES; j++ { | |
incrementPos32(&a, _i) | |
} | |
wg.Done() | |
}(i) | |
} | |
wg.Wait() | |
} | |
} | |
func BenchmarkFalseSharing64(b *testing.B) { | |
a := make([]int64, 4) | |
for n := 0; n < b.N; n++ { | |
var wg sync.WaitGroup | |
for i := 0; i < CPU_COUNT; i++ { | |
wg.Add(1) | |
go func(_i int) { | |
for j := 0; j <= ADD_TIMES; j++ { | |
incrementPos64(&a, _i) | |
} | |
wg.Done() | |
}(i) | |
} | |
wg.Wait() | |
} | |
} |
This file contains 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
type NotPaddedCounter struct { | |
v1 uint64 | |
v2 uint64 | |
v3 uint64 | |
} | |
func (pc *NotPaddedCounter) Increment() { | |
atomic.AddUint64(&pc.v1, 1) | |
atomic.AddUint64(&pc.v2, 1) | |
atomic.AddUint64(&pc.v3, 1) | |
} |
This file contains 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
type PaddedCounter struct { | |
v1 uint64 | |
p1 [8]uint64 | |
v2 uint64 | |
p2 [8]uint64 | |
v3 uint64 | |
p3 [8]uint64 | |
} | |
func (pc *PaddedCounter) Increment() { | |
atomic.AddUint64(&pc.v1, 1) | |
atomic.AddUint64(&pc.v2, 1) | |
atomic.AddUint64(&pc.v3, 1) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment