go/test/tinyfin.go
Dmitriy Vyukov 1fa7029425 runtime: combine small NoScan allocations
Combine NoScan allocations < 16 bytes into a single memory block.
Reduces number of allocations on json/garbage benchmarks by 10+%.

json-1
allocated                 8039872      7949194      -1.13%
allocs                     105774        93776     -11.34%
cputime                 156200000    100700000     -35.53%
gc-pause-one              4908873      3814853     -22.29%
gc-pause-total            2748969      2899288      +5.47%
rss                      52674560     43560960     -17.30%
sys-gc                    3796976      3256304     -14.24%
sys-heap                 43843584     35192832     -19.73%
sys-other                 5589312      5310784      -4.98%
sys-stack                  393216       393216      +0.00%
sys-total                53623088     44153136     -17.66%
time                    156193436    100886714     -35.41%
virtual-mem             256548864    256540672      -0.00%

garbage-1
allocated                 2996885      2932982      -2.13%
allocs                      62904        55200     -12.25%
cputime                  17470000     17400000      -0.40%
gc-pause-one            932757485    925806143      -0.75%
gc-pause-total            4663787      4629030      -0.75%
rss                    1151074304   1133670400      -1.51%
sys-gc                   66068352     65085312      -1.49%
sys-heap               1039728640   1024065536      -1.51%
sys-other                38038208     37485248      -1.45%
sys-stack                 8650752      8781824      +1.52%
sys-total              1152485952   1135417920      -1.48%
time                     17478088     17418005      -0.34%
virtual-mem            1343709184   1324204032      -1.45%

LGTM=iant, bradfitz
R=golang-codereviews, dave, iant, rsc, bradfitz
CC=golang-codereviews, khr
https://golang.org/cl/38750047
2014-01-24 22:35:11 +04:00

63 lines
1.5 KiB
Go

// run
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test finalizers work for tiny (combined) allocations.
package main
import (
"runtime"
"sync/atomic"
"time"
)
func main() {
// Does not work on 32-bits due to partially conservative GC.
// Try to enable when we have fully precise GC.
if runtime.GOARCH != "amd64" {
return
}
// Likewise for gccgo.
if runtime.Compiler == "gccgo" {
return
}
N := int32(100)
count := N
done := make([]bool, N)
for i := int32(0); i < N; i++ {
x := i // subject to tiny alloc
// the closure must be big enough to be combined
runtime.SetFinalizer(&x, func(p *int32) {
// Check that p points to the correct subobject of the tiny allocation.
// It's a bit tricky, because we can't capture another variable
// with the expected value (it would be combined as well).
if *p < 0 || *p >= N {
println("got", *p)
panic("corrupted")
}
if done[*p] {
println("got", *p)
panic("already finalized")
}
done[*p] = true
atomic.AddInt32(&count, -1)
})
}
for i := 0; i < 4; i++ {
runtime.GC()
time.Sleep(10 * time.Millisecond)
}
// Some of the finalizers may not be executed,
// if the outermost allocations are combined with something persistent.
// Currently 4 int32's are combined into a 16-byte block,
// ensure that most of them are finalized.
if count >= N/4 {
println(count, "out of", N, "finalizer are not called")
panic("not all finalizers are called")
}
}