mirror of
https://github.com/golang/go
synced 2024-11-23 00:00:07 -07:00
runtime: do not scan stack by frames during garbage collection
Walking the stack by frames is ~3x more expensive than not, and since it didn't end up being precise, there is not enough benefit to outweigh the cost. This is the conservative choice: this CL makes the stack scanning behavior the same as it was in Go 1.1. Add benchmarks to package runtime so that we have them when we re-enable this feature during the Go 1.3 development. benchmark old ns/op new ns/op delta BenchmarkGoroutineSelect 3194909 1272092 -60.18% BenchmarkGoroutineBlocking 3120282 866366 -72.23% BenchmarkGoroutineForRange 3256179 939902 -71.13% BenchmarkGoroutineIdle 2005571 482982 -75.92% The Go 1 benchmarks, just to add more data. As far as I can tell the changes are mainly noise. benchmark old ns/op new ns/op delta BenchmarkBinaryTree17 4409403046 4414734932 +0.12% BenchmarkFannkuch11 3407708965 3378306120 -0.86% BenchmarkFmtFprintfEmpty 100 99 -0.60% BenchmarkFmtFprintfString 242 239 -1.24% BenchmarkFmtFprintfInt 204 206 +0.98% BenchmarkFmtFprintfIntInt 320 316 -1.25% BenchmarkFmtFprintfPrefixedInt 295 299 +1.36% BenchmarkFmtFprintfFloat 442 435 -1.58% BenchmarkFmtManyArgs 1246 1216 -2.41% BenchmarkGobDecode 10186951 10051210 -1.33% BenchmarkGobEncode 16504381 16445650 -0.36% BenchmarkGzip 447030885 447056865 +0.01% BenchmarkGunzip 111056154 111696305 +0.58% BenchmarkHTTPClientServer 89973 93040 +3.41% BenchmarkJSONEncode 28174182 27933893 -0.85% BenchmarkJSONDecode 106353777 110443817 +3.85% BenchmarkMandelbrot200 4822289 4806083 -0.34% BenchmarkGoParse 6102436 6142734 +0.66% BenchmarkRegexpMatchEasy0_32 133 132 -0.75% BenchmarkRegexpMatchEasy0_1K 372 373 +0.27% BenchmarkRegexpMatchEasy1_32 113 111 -1.77% BenchmarkRegexpMatchEasy1_1K 964 940 -2.49% BenchmarkRegexpMatchMedium_32 202 205 +1.49% BenchmarkRegexpMatchMedium_1K 68862 68858 -0.01% BenchmarkRegexpMatchHard_32 3480 3407 -2.10% BenchmarkRegexpMatchHard_1K 108255 112614 +4.03% BenchmarkRevcomp 751393035 743929976 -0.99% BenchmarkTemplate 139637041 135402220 -3.03% BenchmarkTimeParse 479 475 -0.84% BenchmarkTimeFormat 460 466 +1.30% benchmark old MB/s new MB/s speedup BenchmarkGobDecode 75.34 76.36 1.01x BenchmarkGobEncode 46.50 46.67 1.00x BenchmarkGzip 43.41 43.41 1.00x BenchmarkGunzip 174.73 173.73 0.99x BenchmarkJSONEncode 68.87 69.47 1.01x BenchmarkJSONDecode 18.25 17.57 0.96x BenchmarkGoParse 9.49 9.43 0.99x BenchmarkRegexpMatchEasy0_32 239.58 241.74 1.01x BenchmarkRegexpMatchEasy0_1K 2749.74 2738.00 1.00x BenchmarkRegexpMatchEasy1_32 282.49 286.32 1.01x BenchmarkRegexpMatchEasy1_1K 1062.00 1088.96 1.03x BenchmarkRegexpMatchMedium_32 4.93 4.86 0.99x BenchmarkRegexpMatchMedium_1K 14.87 14.87 1.00x BenchmarkRegexpMatchHard_32 9.19 9.39 1.02x BenchmarkRegexpMatchHard_1K 9.46 9.09 0.96x BenchmarkRevcomp 338.26 341.65 1.01x BenchmarkTemplate 13.90 14.33 1.03x Fixes #6482. R=golang-dev, dave, r CC=golang-dev https://golang.org/cl/14257043
This commit is contained in:
parent
6b188ef57a
commit
c3dadca977
@ -5,8 +5,10 @@
|
||||
package runtime_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
. "runtime"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -65,3 +67,90 @@ func BenchmarkMallocTypeInfo16(b *testing.B) {
|
||||
}
|
||||
mallocSink = x
|
||||
}
|
||||
|
||||
var n = flag.Int("n", 1000, "number of goroutines")
|
||||
|
||||
func BenchmarkGoroutineSelect(b *testing.B) {
|
||||
quit := make(chan struct{})
|
||||
read := func(ch chan struct{}) {
|
||||
for {
|
||||
select {
|
||||
case _, ok := <-ch:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
benchHelper(b, *n, read)
|
||||
}
|
||||
|
||||
func BenchmarkGoroutineBlocking(b *testing.B) {
|
||||
read := func(ch chan struct{}) {
|
||||
for {
|
||||
if _, ok := <-ch; !ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
benchHelper(b, *n, read)
|
||||
}
|
||||
|
||||
func BenchmarkGoroutineForRange(b *testing.B) {
|
||||
read := func(ch chan struct{}) {
|
||||
for _ = range ch {
|
||||
}
|
||||
}
|
||||
benchHelper(b, *n, read)
|
||||
}
|
||||
|
||||
func benchHelper(b *testing.B, n int, read func(chan struct{})) {
|
||||
m := make([]chan struct{}, n)
|
||||
for i := range m {
|
||||
m[i] = make(chan struct{}, 1)
|
||||
go read(m[i])
|
||||
}
|
||||
b.StopTimer()
|
||||
b.ResetTimer()
|
||||
GC()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, ch := range m {
|
||||
if ch != nil {
|
||||
ch <- struct{}{}
|
||||
}
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
b.StartTimer()
|
||||
GC()
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
for _, ch := range m {
|
||||
close(ch)
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
func BenchmarkGoroutineIdle(b *testing.B) {
|
||||
quit := make(chan struct{})
|
||||
fn := func() {
|
||||
<-quit
|
||||
}
|
||||
for i := 0; i < *n; i++ {
|
||||
go fn()
|
||||
}
|
||||
|
||||
GC()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
GC()
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
close(quit)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ enum {
|
||||
Debug = 0,
|
||||
DebugMark = 0, // run second pass to check mark
|
||||
CollectStats = 0,
|
||||
ScanStackByFrames = 1,
|
||||
ScanStackByFrames = 0,
|
||||
IgnorePreciseGC = 0,
|
||||
|
||||
// Four bits per word (see #defines below).
|
||||
@ -1474,6 +1474,7 @@ addstackroots(G *gp)
|
||||
USED(guard);
|
||||
runtime·gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, addframeroots, nil, false);
|
||||
} else {
|
||||
USED(lr);
|
||||
USED(pc);
|
||||
n = 0;
|
||||
while(stk) {
|
||||
|
Loading…
Reference in New Issue
Block a user