Skip to content

Instantly share code, notes, and snippets.

@TimRots
Created June 28, 2020 18:26
Show Gist options
  • Save TimRots/3cb20028a844a575af3d84b62c63d53e to your computer and use it in GitHub Desktop.
Save TimRots/3cb20028a844a575af3d84b62c63d53e to your computer and use it in GitHub Desktop.
Measure the costs of context switching for the OS and a Go application
#!/usr/bin/env bash
# Tim Rots - June 2020
#
# This benchmark measures the costs of context switching for the OS and a Go application in usec/op.
#
# Usage:
# $ ./measure_cs.sh
# OS: 2.19416 usec/op
# Go: 0.16 usec/op
# Difference: 86%
# Check dependencies
if [ -z "$(which perf)" ] || [ -z "$(which go)" ] ;
then
echo "Error - Dependency missing\nEnsure perf and Go are installed correctly."; exit 1
fi
# Ensure Go benchmark
goBenchmark=/tmp/context_switch_test.go
if [ ! -e "${goBenchmark}" ];
then
cat > "${goBenchmark}"<<EOF
package main
import (
"sync"
"testing"
)
func BenchmarkContextSwitch(b *testing.B) {
var wg sync.WaitGroup
begin := make(chan struct{})
c := make(chan struct{})
var token struct{}
sender := func() {
defer wg.Done()
<-begin
for i := 0; i < b.N; i++ {
c <- token
}
}
receiver := func() {
defer wg.Done()
<-begin
for i := 0; i < b.N; i++ {
<-c
}
}
wg.Add(2)
go sender()
go receiver()
b.StartTimer()
close(begin)
wg.Wait()
}
EOF
fi
# Measure context-switch in usec/op
# Print result per test-item, and show difference in %
contextSwitchOs=$(taskset -c 0 perf bench sched pipe -T|awk '/usecs/{print (($1/2))}')
contextSwitchGo=$(go test -bench=. -cpu=1 ${goBenchmark} |awk '/BenchmarkContextSwitch/{print (($3/1000))}')
echo "OS: ${contextSwitchOs} usec/op"
echo "Go: ${contextSwitchGo} usec/op"
echo "${contextSwitchOs}" "${contextSwitchGo}"|awk '{diff = ($1-$2)/($1+$2)*100; print "Difference: "substr(diff,1,2)"%"}'
# Cleanup
rm ${goBenchmark}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment