Created
November 8, 2021 08:00
-
-
Save ansiwen/acb25f88653c189a99dfa3ca35797b3f to your computer and use it in GitHub Desktop.
Pinner Research Benchmarks
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 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) | |
} |
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 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") | |
} | |
} | |
}) | |
} |
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
% /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 | |
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 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