| // Copyright 2013 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. |
| |
| package runtime_test |
| |
| import ( |
| "flag" |
| . "runtime" |
| "testing" |
| "time" |
| "unsafe" |
| ) |
| |
| func TestMemStats(t *testing.T) { |
| // Test that MemStats has sane values. |
| st := new(MemStats) |
| ReadMemStats(st) |
| if st.HeapSys == 0 || st.StackSys == 0 || st.MSpanSys == 0 || st.MCacheSys == 0 || |
| st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 { |
| t.Fatalf("Zero sys value: %+v", *st) |
| } |
| if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+ |
| st.BuckHashSys+st.GCSys+st.OtherSys { |
| t.Fatalf("Bad sys value: %+v", *st) |
| } |
| } |
| |
| var mallocSink uintptr |
| |
| func BenchmarkMalloc8(b *testing.B) { |
| var x uintptr |
| for i := 0; i < b.N; i++ { |
| p := new(int64) |
| x ^= uintptr(unsafe.Pointer(p)) |
| } |
| mallocSink = x |
| } |
| |
| func BenchmarkMalloc16(b *testing.B) { |
| var x uintptr |
| for i := 0; i < b.N; i++ { |
| p := new([2]int64) |
| x ^= uintptr(unsafe.Pointer(p)) |
| } |
| mallocSink = x |
| } |
| |
| func BenchmarkMallocTypeInfo8(b *testing.B) { |
| var x uintptr |
| for i := 0; i < b.N; i++ { |
| p := new(struct { |
| p [8 / unsafe.Sizeof(uintptr(0))]*int |
| }) |
| x ^= uintptr(unsafe.Pointer(p)) |
| } |
| mallocSink = x |
| } |
| |
| func BenchmarkMallocTypeInfo16(b *testing.B) { |
| var x uintptr |
| for i := 0; i < b.N; i++ { |
| p := new(struct { |
| p [16 / unsafe.Sizeof(uintptr(0))]*int |
| }) |
| x ^= uintptr(unsafe.Pointer(p)) |
| } |
| 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) |
| } |