Skip to content

Instantly share code, notes, and snippets.

@dariodip
Last active March 25, 2021 22:17
Show Gist options
  • Save dariodip/f289918b9f750b10ec962cd8ff2ae0c6 to your computer and use it in GitHub Desktop.
Save dariodip/f289918b9f750b10ec962cd8ff2ae0c6 to your computer and use it in GitHub Desktop.
False Sharing in Go
type Counter interface {
Increment()
}
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)
}
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]++
}
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()
}
}
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)
}
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