| // 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) | |
| } |