1
0
mirror of https://github.com/golang/go synced 2024-11-19 15:34:47 -07:00

runtime: add benchmark for write barriers

For #22460.

Change-Id: I798f26d45bbe1efd16b632e201413cb26cb3e6c7
Reviewed-on: https://go-review.googlesource.com/73811
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2017-10-24 11:56:00 -04:00
parent 15d6ab69fb
commit 1e8ab99b37

View File

@ -10,6 +10,7 @@ import (
"reflect"
"runtime"
"runtime/debug"
"sync/atomic"
"testing"
"time"
"unsafe"
@ -515,3 +516,83 @@ func TestUserForcedGC(t *testing.T) {
t.Fatalf("runtime.GC() was not accounted in NumForcedGC")
}
}
func BenchmarkWriteBarrier(b *testing.B) {
if runtime.GOMAXPROCS(-1) < 2 {
// We don't want GC to take our time.
b.Skip("need GOMAXPROCS >= 2")
}
// Construct a large tree both so the GC runs for a while and
// so we have a data structure to manipulate the pointers of.
type node struct {
l, r *node
}
var wbRoots []*node
var mkTree func(level int) *node
mkTree = func(level int) *node {
if level == 0 {
return nil
}
n := &node{mkTree(level - 1), mkTree(level - 1)}
if level == 10 {
// Seed GC with enough early pointers so it
// doesn't accidentally switch to mark 2 when
// it only has the top of the tree.
wbRoots = append(wbRoots, n)
}
return n
}
const depth = 22 // 64 MB
root := mkTree(22)
runtime.GC()
var ms runtime.MemStats
runtime.ReadMemStats(&ms)
//b.Logf("heap size: %d MB", ms.HeapAlloc>>20)
// Keep GC running continuously during the benchmark.
var stop uint32
done := make(chan bool)
go func() {
for atomic.LoadUint32(&stop) == 0 {
runtime.GC()
}
close(done)
}()
b.ResetTimer()
var stack [depth]*node
tos := -1
// There are two write barriers per iteration, so i+=2.
for i := 0; i < b.N; i += 2 {
if tos == -1 {
stack[0] = root
tos = 0
}
// Perform one step of reversing the tree.
n := stack[tos]
if n.l == nil {
tos--
} else {
n.l, n.r = n.r, n.l
stack[tos] = n.l
stack[tos+1] = n.r
tos++
}
if i%(1<<12) == 0 {
// Avoid non-preemptible loops (see issue #10958).
runtime.Gosched()
}
}
b.StopTimer()
atomic.StoreUint32(&stop, 1)
<-done
runtime.KeepAlive(wbRoots)
}