diff options
| author | Russ Cox <rsc@golang.org> | 2013-10-02 11:59:53 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2013-10-02 11:59:53 -0400 |
| commit | c3dadca9776b6f1c32ee088698e8584636bba2fb (patch) | |
| tree | a96014da528b8fe357c6d985356f0a587623f2b2 /src/pkg/runtime/malloc_test.go | |
| parent | 6b188ef57a644838bd4c673d6d14b49879db6297 (diff) | |
| download | go-c3dadca9776b6f1c32ee088698e8584636bba2fb.tar.xz | |
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
Diffstat (limited to 'src/pkg/runtime/malloc_test.go')
| -rw-r--r-- | src/pkg/runtime/malloc_test.go | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/pkg/runtime/malloc_test.go b/src/pkg/runtime/malloc_test.go index 2b686a6e7e..128ec098cb 100644 --- a/src/pkg/runtime/malloc_test.go +++ b/src/pkg/runtime/malloc_test.go @@ -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) +} |
