mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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:
parent
15d6ab69fb
commit
1e8ab99b37
1 changed files with 81 additions and 0 deletions
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
@ -515,3 +516,83 @@ func TestUserForcedGC(t *testing.T) {
|
||||||
t.Fatalf("runtime.GC() was not accounted in NumForcedGC")
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue