mirror of
https://github.com/golang/go
synced 2024-11-18 07:54:55 -07:00
runtime: add benchmark of heapBitsSetType
There was an old benchmark that measured this indirectly via allocation, but I don't understand how to factor out the allocation cost when interpreting the numbers. Replace with a benchmark that only calls heapBitsSetType, that does not allocate. This was not possible when the benchmark was first written, because heapBitsSetType had not been factored out of mallocgc. Change-Id: I30f0f02362efab3465a50769398be859832e6640 Reviewed-on: https://go-review.googlesource.com/9701 Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
db6f88a84b
commit
7d9e16abc6
@ -128,3 +128,32 @@ func Envs() []string { return envs }
|
||||
func SetEnvs(e []string) { envs = e }
|
||||
|
||||
var BigEndian = _BigEndian
|
||||
|
||||
// For benchmarking.
|
||||
|
||||
func BenchSetType(n int, x interface{}) {
|
||||
e := *(*eface)(unsafe.Pointer(&x))
|
||||
t := e._type
|
||||
var size uintptr
|
||||
var p unsafe.Pointer
|
||||
switch t.kind & kindMask {
|
||||
case _KindPtr:
|
||||
t = (*ptrtype)(unsafe.Pointer(t)).elem
|
||||
size = t.size
|
||||
p = e.data
|
||||
case _KindSlice:
|
||||
slice := *(*struct {
|
||||
ptr unsafe.Pointer
|
||||
len, cap uintptr
|
||||
})(e.data)
|
||||
t = (*slicetype)(unsafe.Pointer(t)).elem
|
||||
size = t.size * slice.len
|
||||
p = slice.ptr
|
||||
}
|
||||
allocSize := roundupsize(size)
|
||||
systemstack(func() {
|
||||
for i := 0; i < n; i++ {
|
||||
heapBitsSetType(uintptr(p), allocSize, size, t)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package runtime_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"testing"
|
||||
@ -197,45 +198,140 @@ func TestHugeGCInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNoPtr1(b *testing.B) {
|
||||
type NoPtr1 struct {
|
||||
p uintptr
|
||||
func BenchmarkSetTypePtr(b *testing.B) {
|
||||
benchSetType(b, new(*byte))
|
||||
}
|
||||
var p *NoPtr1
|
||||
for i := 0; i < b.N; i++ {
|
||||
p = &NoPtr1{}
|
||||
|
||||
func BenchmarkSetTypePtr8(b *testing.B) {
|
||||
benchSetType(b, new([8]*byte))
|
||||
}
|
||||
_ = p
|
||||
|
||||
func BenchmarkSetTypePtr16(b *testing.B) {
|
||||
benchSetType(b, new([16]*byte))
|
||||
}
|
||||
func BenchmarkSetTypeNoPtr2(b *testing.B) {
|
||||
type NoPtr2 struct {
|
||||
p, q uintptr
|
||||
|
||||
func BenchmarkSetTypePtr32(b *testing.B) {
|
||||
benchSetType(b, new([32]*byte))
|
||||
}
|
||||
var p *NoPtr2
|
||||
for i := 0; i < b.N; i++ {
|
||||
p = &NoPtr2{}
|
||||
|
||||
func BenchmarkSetTypePtr64(b *testing.B) {
|
||||
benchSetType(b, new([64]*byte))
|
||||
}
|
||||
_ = p
|
||||
|
||||
func BenchmarkSetTypePtr126(b *testing.B) {
|
||||
benchSetType(b, new([126]*byte))
|
||||
}
|
||||
func BenchmarkSetTypePtr1(b *testing.B) {
|
||||
type Ptr1 struct {
|
||||
p *byte
|
||||
|
||||
func BenchmarkSetTypePtr128(b *testing.B) {
|
||||
benchSetType(b, new([128]*byte))
|
||||
}
|
||||
var p *Ptr1
|
||||
for i := 0; i < b.N; i++ {
|
||||
p = &Ptr1{}
|
||||
|
||||
func BenchmarkSetTypePtrSlice(b *testing.B) {
|
||||
benchSetType(b, make([]*byte, 1<<10))
|
||||
}
|
||||
_ = p
|
||||
|
||||
type Node1 struct {
|
||||
Value [1]uintptr
|
||||
Left, Right *byte
|
||||
}
|
||||
func BenchmarkSetTypePtr2(b *testing.B) {
|
||||
type Ptr2 struct {
|
||||
p, q *byte
|
||||
|
||||
func BenchmarkSetTypeNode1(b *testing.B) {
|
||||
benchSetType(b, new(Node1))
|
||||
}
|
||||
var p *Ptr2
|
||||
for i := 0; i < b.N; i++ {
|
||||
p = &Ptr2{}
|
||||
|
||||
func BenchmarkSetTypeNode1Slice(b *testing.B) {
|
||||
benchSetType(b, make([]Node1, 32))
|
||||
}
|
||||
_ = p
|
||||
|
||||
type Node8 struct {
|
||||
Value [8]uintptr
|
||||
Left, Right *byte
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode8(b *testing.B) {
|
||||
benchSetType(b, new(Node8))
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode8Slice(b *testing.B) {
|
||||
benchSetType(b, make([]Node8, 32))
|
||||
}
|
||||
|
||||
type Node64 struct {
|
||||
Value [64]uintptr
|
||||
Left, Right *byte
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode64(b *testing.B) {
|
||||
benchSetType(b, new(Node64))
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode64Slice(b *testing.B) {
|
||||
benchSetType(b, make([]Node64, 32))
|
||||
}
|
||||
|
||||
type Node64Dead struct {
|
||||
Left, Right *byte
|
||||
Value [64]uintptr
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode64Dead(b *testing.B) {
|
||||
benchSetType(b, new(Node64Dead))
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode64DeadSlice(b *testing.B) {
|
||||
benchSetType(b, make([]Node64Dead, 32))
|
||||
}
|
||||
|
||||
type Node124 struct {
|
||||
Value [124]uintptr
|
||||
Left, Right *byte
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode124(b *testing.B) {
|
||||
benchSetType(b, new(Node124))
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode124Slice(b *testing.B) {
|
||||
benchSetType(b, make([]Node124, 32))
|
||||
}
|
||||
|
||||
type Node126 struct {
|
||||
Value [126]uintptr
|
||||
Left, Right *byte
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode126(b *testing.B) {
|
||||
benchSetType(b, new(Node126))
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode126Slice(b *testing.B) {
|
||||
benchSetType(b, make([]Node126, 32))
|
||||
}
|
||||
|
||||
type Node1024 struct {
|
||||
Value [1024]uintptr
|
||||
Left, Right *byte
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode1024(b *testing.B) {
|
||||
benchSetType(b, new(Node1024))
|
||||
}
|
||||
|
||||
func BenchmarkSetTypeNode1024Slice(b *testing.B) {
|
||||
benchSetType(b, make([]Node1024, 32))
|
||||
}
|
||||
|
||||
func benchSetType(b *testing.B, x interface{}) {
|
||||
v := reflect.ValueOf(x)
|
||||
t := v.Type()
|
||||
switch t.Kind() {
|
||||
case reflect.Ptr:
|
||||
b.SetBytes(int64(t.Elem().Size()))
|
||||
case reflect.Slice:
|
||||
b.SetBytes(int64(t.Elem().Size()) * int64(v.Len()))
|
||||
}
|
||||
b.ResetTimer()
|
||||
runtime.BenchSetType(b.N, x)
|
||||
}
|
||||
|
||||
func BenchmarkAllocation(b *testing.B) {
|
||||
|
Loading…
Reference in New Issue
Block a user