diff options
| author | Dmitriy Vyukov <dvyukov@google.com> | 2013-01-10 09:57:06 +0400 |
|---|---|---|
| committer | Dmitriy Vyukov <dvyukov@google.com> | 2013-01-10 09:57:06 +0400 |
| commit | f82db7d9e4ccf04b19a087561ab0f521fc36e5b1 (patch) | |
| tree | 17307311faba0dc26fadc8044e0808fc6ee04a4d /src/pkg/runtime/stack_test.go | |
| parent | 7d403871cb7e319cb1f52ce2ff04c80bdc5ac92a (diff) | |
| download | go-f82db7d9e4ccf04b19a087561ab0f521fc36e5b1.tar.xz | |
runtime: less aggressive per-thread stack segment caching
Introduce global stack segment cache and limit per-thread cache size.
This greatly reduces StackSys memory on workloads that create lots of threads.
benchmark old ns/op new ns/op delta
BenchmarkStackGrowth 665 656 -1.35%
BenchmarkStackGrowth-2 333 328 -1.50%
BenchmarkStackGrowth-4 224 172 -23.21%
BenchmarkStackGrowth-8 124 91 -26.13%
BenchmarkStackGrowth-16 82 47 -41.94%
BenchmarkStackGrowth-32 73 40 -44.79%
BenchmarkStackGrowthDeep 97231 94391 -2.92%
BenchmarkStackGrowthDeep-2 47230 58562 +23.99%
BenchmarkStackGrowthDeep-4 24993 49356 +97.48%
BenchmarkStackGrowthDeep-8 15105 30072 +99.09%
BenchmarkStackGrowthDeep-16 10005 15623 +56.15%
BenchmarkStackGrowthDeep-32 12517 13069 +4.41%
TestStackMem#1,MB 310 12 -96.13%
TestStackMem#2,MB 296 14 -95.27%
TestStackMem#3,MB 479 14 -97.08%
TestStackMem#1,sec 3.22 2.26 -29.81%
TestStackMem#2,sec 2.43 2.15 -11.52%
TestStackMem#3,sec 2.50 2.38 -4.80%
R=sougou, no.smile.face, rsc
CC=golang-dev, msolomon
https://golang.org/cl/7029044
Diffstat (limited to 'src/pkg/runtime/stack_test.go')
| -rw-r--r-- | src/pkg/runtime/stack_test.go | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/pkg/runtime/stack_test.go b/src/pkg/runtime/stack_test.go index 8b75e4d121..f04bddc764 100644 --- a/src/pkg/runtime/stack_test.go +++ b/src/pkg/runtime/stack_test.go @@ -34,6 +34,7 @@ package runtime_test import ( . "runtime" "testing" + "time" "unsafe" ) @@ -1526,3 +1527,51 @@ func stack4988() (uintptr, uintptr) { var buf [4988]byte; use(buf[:]); return St func stack4992() (uintptr, uintptr) { var buf [4992]byte; use(buf[:]); return Stackguard() } func stack4996() (uintptr, uintptr) { var buf [4996]byte; use(buf[:]); return Stackguard() } func stack5000() (uintptr, uintptr) { var buf [5000]byte; use(buf[:]); return Stackguard() } + +// TestStackMem measures per-thread stack segment cache behavior. +// The test consumed up to 500MB in the past. +func TestStackMem(t *testing.T) { + const ( + BatchSize = 32 + BatchCount = 512 + ArraySize = 1024 + RecursionDepth = 128 + ) + if testing.Short() { + return + } + defer GOMAXPROCS(GOMAXPROCS(BatchSize)) + s0 := new(MemStats) + ReadMemStats(s0) + for b := 0; b < BatchCount; b++ { + c := make(chan bool, BatchSize) + for i := 0; i < BatchSize; i++ { + go func() { + var f func(k int, a [ArraySize]byte) + f = func(k int, a [ArraySize]byte) { + if k == 0 { + time.Sleep(time.Millisecond) + return + } + f(k-1, a) + } + f(RecursionDepth, [ArraySize]byte{}) + c <- true + }() + } + for i := 0; i < BatchSize; i++ { + <-c + } + } + s1 := new(MemStats) + ReadMemStats(s1) + consumed := s1.StackSys - s0.StackSys + t.Logf("Consumed %vMB for stack mem", consumed>>20) + estimate := uint64(8 * BatchSize * ArraySize * RecursionDepth) // 8 is to reduce flakiness. + if consumed > estimate { + t.Fatalf("Stack mem: want %v, got %v", estimate, consumed) + } + if s1.StackInuse > 1<<20 { + t.Fatalf("Stack inuse: want %v, got %v", 1<<20, s1.StackInuse) + } +} |
