Skip to content

Instantly share code, notes, and snippets.

@ansiwen
Created November 8, 2021 08:00
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 ansiwen/acb25f88653c189a99dfa3ca35797b3f to your computer and use it in GitHub Desktop.
Save ansiwen/acb25f88653c189a99dfa3ca35797b3f to your computer and use it in GitHub Desktop.
Pinner Research Benchmarks
package pinnerbenchmark
/*
inline void* ccall0() {
return NULL;
}
inline void* ccall1(void* p) {
return NULL;
}
inline void* ccall4(void* p, void* p2, void* p3, void* p4) {
return NULL;
}
*/
import "C"
import "unsafe"
var (
buffer []byte
somePtr unsafe.Pointer
)
func init() {
buffer = []byte("foobar")
somePtr = unsafe.Pointer(&buffer[0])
}
func cCall0() unsafe.Pointer {
return C.ccall0()
}
func cCall1() unsafe.Pointer {
return C.ccall1(somePtr)
}
func cCall4() unsafe.Pointer {
return C.ccall4(somePtr, somePtr, somePtr, somePtr)
}
package pinnerbenchmark
import (
"math/rand"
"sync"
"testing"
)
func BenchmarkCCall0NoCgoCheck(b *testing.B) {
old := *cgocheck
*cgocheck = 0
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if cCall0() != nil {
b.Errorf("can't happen")
}
}
})
*cgocheck = old
}
func BenchmarkCCall0(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if cCall0() != nil {
b.Errorf("can't happen")
}
}
})
}
func BenchmarkCCall1NoCgoCheck(b *testing.B) {
old := *cgocheck
*cgocheck = 0
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if cCall1() != nil {
b.Errorf("can't happen")
}
}
})
*cgocheck = old
}
func BenchmarkCCall1(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if cCall1() != nil {
b.Errorf("can't happen")
}
}
})
}
func BenchmarkCCall4NoCgoCheck(b *testing.B) {
old := *cgocheck
*cgocheck = 0
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if cCall4() != nil {
b.Errorf("can't happen")
}
}
})
*cgocheck = old
}
func BenchmarkCCall4(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if cCall4() != nil {
b.Errorf("can't happen")
}
}
})
}
func BenchmarkSyncMap(b *testing.B) {
mapSize := 10
var m sync.Map
for n := 0; n < mapSize; n++ {
m.Store(uintptr(rand.Uint64()&1), nil)
}
x := uintptr(rand.Uint64() &^ 1)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, found := m.Load(x); found {
b.Errorf("can't happen")
}
}
})
}
func BenchmarkMap(b *testing.B) {
mapSize := 10
type void struct{}
var set void
m := make(map[uintptr]void)
for n := 0; n < mapSize; n++ {
m[uintptr(rand.Uint64()&1)] = set
}
x := uintptr(rand.Uint64() &^ 1)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, found := m[x]; found {
b.Errorf("can't happen")
}
}
})
}
func BenchmarkMutexMap(b *testing.B) {
mapSize := 10
type void struct{}
var set void
var mtx sync.Mutex
m := make(map[uintptr]void)
for n := 0; n < mapSize; n++ {
m[uintptr(rand.Uint64()&1)] = set
}
x := uintptr(rand.Uint64() &^ 1)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
mtx.Lock()
if _, found := m[x]; found {
b.Errorf("can't happen")
}
mtx.Unlock()
}
})
}
func BenchmarkRWMutexMap(b *testing.B) {
mapSize := 10
type void struct{}
var set void
var mtx sync.RWMutex
m := make(map[uintptr]void)
for n := 0; n < mapSize; n++ {
m[uintptr(rand.Uint64()&1)] = set
}
x := uintptr(rand.Uint64() &^ 1)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
mtx.RLock()
if _, found := m[x]; found {
b.Errorf("can't happen")
}
mtx.RUnlock()
}
})
}
func BenchmarkSpecials(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
r := removespecial(somePtr, 1)
if r != nil {
b.Errorf("can't happen")
}
}
})
}
func BenchmarkSpecialsWithoutLocks(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
r := hasspecial(somePtr, 1)
if r {
b.Errorf("can't happen")
}
}
})
}
% /Users/svanders/sdk/go1.17.3/bin/go test -run=^$ -bench . pinnerbenchmark -benchtime 1s -c
goos: darwin
goarch: amd64
pkg: pinnerbenchmark
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkCCall0NoCgoCheck 19683577 55.13 ns/op
BenchmarkCCall0 21328222 55.03 ns/op
BenchmarkCCall1NoCgoCheck 18208592 60.48 ns/op |
BenchmarkCCall1 16470044 74.33 ns/op |
BenchmarkCCall4NoCgoCheck 16455018 63.66 ns/op |-> ~14.3ns / ptr
BenchmarkCCall4 9597632 121.3 ns/op |
BenchmarkSyncMap 92286345 13.34 ns/op +93% / ptr
BenchmarkMap 220817404 5.263 ns/op +36% / ptr
BenchmarkMutexMap 80391705 14.63 ns/op +102% / ptr
BenchmarkRWMutexMap 81198786 14.75 ns/op +103% / ptr
BenchmarkSpecials 51773179 23.25 ns/op +163% / ptr
BenchmarkSpecialsWithoutLocks 275029039 4.281 ns/op +30% / ptr
package pinnerbenchmark
import "unsafe" // enable go:linkname
//go:linkname removespecial runtime.removespecial
func removespecial(p unsafe.Pointer, kind uint8) unsafe.Pointer
//go:linkname hasspecial runtime.hasspecial
func hasspecial(p unsafe.Pointer, kind uint8) bool
/* added to runtime/mheap.go:
func hasspecial(p unsafe.Pointer, kind uint8) bool {
span := spanOfHeap(uintptr(p))
if span == nil {
throw("removespecial on invalid pointer")
}
offset := uintptr(p) - span.base()
s := span.specials
for {
if s == nil || uintptr(s.offset) > offset{
break
}
// This function is used for finalizers only, so we don't check
// "interior" specials (p must be exactly equal to s->offset).
if offset == uintptr(s.offset) {
if s.kind > kind {
break
}
if s.kind == kind {
return true
}
}
s = s.next
}
return false
}
*/
type _dbgVar struct {
name string
value *int32
}
//go:linkname _dbgvars runtime.dbgvars
var _dbgvars []_dbgVar
var cgocheck = func() *int32 {
for i := range _dbgvars {
if _dbgvars[i].name == "cgocheck" {
return _dbgvars[i].value
}
}
panic("Couln't find cgocheck debug variable")
}()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment