Dmitriy Vyukov | 915784e | 2013-05-15 21:22:32 +0400 | [diff] [blame] | 1 | // Copyright 2013 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package runtime_test |
| 6 | |
| 7 | import ( |
Russ Cox | c3dadca | 2013-10-02 11:59:53 -0400 | [diff] [blame] | 8 | "flag" |
Dmitriy Vyukov | a33ef8d | 2013-09-06 16:55:40 -0400 | [diff] [blame] | 9 | . "runtime" |
Dmitriy Vyukov | 915784e | 2013-05-15 21:22:32 +0400 | [diff] [blame] | 10 | "testing" |
Russ Cox | c3dadca | 2013-10-02 11:59:53 -0400 | [diff] [blame] | 11 | "time" |
Dmitriy Vyukov | 915784e | 2013-05-15 21:22:32 +0400 | [diff] [blame] | 12 | "unsafe" |
| 13 | ) |
| 14 | |
Dmitriy Vyukov | a33ef8d | 2013-09-06 16:55:40 -0400 | [diff] [blame] | 15 | func TestMemStats(t *testing.T) { |
| 16 | // Test that MemStats has sane values. |
| 17 | st := new(MemStats) |
| 18 | ReadMemStats(st) |
Dmitriy Vyukov | 30ef2c7 | 2014-08-19 11:46:05 +0400 | [diff] [blame^] | 19 | |
| 20 | // Everything except HeapReleased, because it indeed can be 0. |
| 21 | if st.Alloc == 0 || st.TotalAlloc == 0 || st.Sys == 0 || st.Lookups == 0 || |
| 22 | st.Mallocs == 0 || st.Frees == 0 || st.HeapAlloc == 0 || st.HeapSys == 0 || |
| 23 | st.HeapIdle == 0 || st.HeapInuse == 0 || st.HeapObjects == 0 || st.StackInuse == 0 || |
| 24 | st.StackSys == 0 || st.MSpanInuse == 0 || st.MSpanSys == 0 || st.MCacheInuse == 0 || |
| 25 | st.MCacheSys == 0 || st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 || |
| 26 | st.NextGC == 0 || st.NumGC == 0 { |
| 27 | t.Fatalf("Zero value: %+v", *st) |
Dmitriy Vyukov | a33ef8d | 2013-09-06 16:55:40 -0400 | [diff] [blame] | 28 | } |
Dmitriy Vyukov | 30ef2c7 | 2014-08-19 11:46:05 +0400 | [diff] [blame^] | 29 | |
| 30 | if st.Alloc > 1e10 || st.TotalAlloc > 1e11 || st.Sys > 1e10 || st.Lookups > 1e10 || |
| 31 | st.Mallocs > 1e10 || st.Frees > 1e10 || st.HeapAlloc > 1e10 || st.HeapSys > 1e10 || |
| 32 | st.HeapIdle > 1e10 || st.HeapInuse > 1e10 || st.HeapObjects > 1e10 || st.StackInuse > 1e10 || |
| 33 | st.StackSys > 1e10 || st.MSpanInuse > 1e10 || st.MSpanSys > 1e10 || st.MCacheInuse > 1e10 || |
| 34 | st.MCacheSys > 1e10 || st.BuckHashSys > 1e10 || st.GCSys > 1e10 || st.OtherSys > 1e10 || |
| 35 | st.NextGC > 1e10 || st.NumGC > 1e9 { |
| 36 | t.Fatalf("Insanely high value (overflow?): %+v", *st) |
| 37 | } |
| 38 | |
Dmitriy Vyukov | a33ef8d | 2013-09-06 16:55:40 -0400 | [diff] [blame] | 39 | if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+ |
| 40 | st.BuckHashSys+st.GCSys+st.OtherSys { |
| 41 | t.Fatalf("Bad sys value: %+v", *st) |
| 42 | } |
| 43 | } |
| 44 | |
Dmitriy Vyukov | 915784e | 2013-05-15 21:22:32 +0400 | [diff] [blame] | 45 | var mallocSink uintptr |
| 46 | |
| 47 | func BenchmarkMalloc8(b *testing.B) { |
| 48 | var x uintptr |
| 49 | for i := 0; i < b.N; i++ { |
| 50 | p := new(int64) |
| 51 | x ^= uintptr(unsafe.Pointer(p)) |
| 52 | } |
| 53 | mallocSink = x |
| 54 | } |
| 55 | |
| 56 | func BenchmarkMalloc16(b *testing.B) { |
| 57 | var x uintptr |
| 58 | for i := 0; i < b.N; i++ { |
| 59 | p := new([2]int64) |
| 60 | x ^= uintptr(unsafe.Pointer(p)) |
| 61 | } |
| 62 | mallocSink = x |
| 63 | } |
| 64 | |
| 65 | func BenchmarkMallocTypeInfo8(b *testing.B) { |
| 66 | var x uintptr |
| 67 | for i := 0; i < b.N; i++ { |
| 68 | p := new(struct { |
| 69 | p [8 / unsafe.Sizeof(uintptr(0))]*int |
| 70 | }) |
| 71 | x ^= uintptr(unsafe.Pointer(p)) |
| 72 | } |
| 73 | mallocSink = x |
| 74 | } |
| 75 | |
| 76 | func BenchmarkMallocTypeInfo16(b *testing.B) { |
| 77 | var x uintptr |
| 78 | for i := 0; i < b.N; i++ { |
| 79 | p := new(struct { |
| 80 | p [16 / unsafe.Sizeof(uintptr(0))]*int |
| 81 | }) |
| 82 | x ^= uintptr(unsafe.Pointer(p)) |
| 83 | } |
| 84 | mallocSink = x |
| 85 | } |
Russ Cox | c3dadca | 2013-10-02 11:59:53 -0400 | [diff] [blame] | 86 | |
Dmitriy Vyukov | cd17a71 | 2014-07-29 11:01:02 +0400 | [diff] [blame] | 87 | type LargeStruct struct { |
| 88 | x [16][]byte |
| 89 | } |
| 90 | |
| 91 | func BenchmarkMallocLargeStruct(b *testing.B) { |
| 92 | var x uintptr |
| 93 | for i := 0; i < b.N; i++ { |
| 94 | p := make([]LargeStruct, 2) |
| 95 | x ^= uintptr(unsafe.Pointer(&p[0])) |
| 96 | } |
| 97 | mallocSink = x |
| 98 | } |
| 99 | |
Russ Cox | c3dadca | 2013-10-02 11:59:53 -0400 | [diff] [blame] | 100 | var n = flag.Int("n", 1000, "number of goroutines") |
| 101 | |
| 102 | func BenchmarkGoroutineSelect(b *testing.B) { |
| 103 | quit := make(chan struct{}) |
| 104 | read := func(ch chan struct{}) { |
| 105 | for { |
| 106 | select { |
| 107 | case _, ok := <-ch: |
| 108 | if !ok { |
| 109 | return |
| 110 | } |
| 111 | case <-quit: |
| 112 | return |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | benchHelper(b, *n, read) |
| 117 | } |
| 118 | |
| 119 | func BenchmarkGoroutineBlocking(b *testing.B) { |
| 120 | read := func(ch chan struct{}) { |
| 121 | for { |
| 122 | if _, ok := <-ch; !ok { |
| 123 | return |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | benchHelper(b, *n, read) |
| 128 | } |
| 129 | |
| 130 | func BenchmarkGoroutineForRange(b *testing.B) { |
| 131 | read := func(ch chan struct{}) { |
Robert Griesemer | 8a23c00 | 2014-07-16 16:29:51 -0700 | [diff] [blame] | 132 | for range ch { |
Russ Cox | c3dadca | 2013-10-02 11:59:53 -0400 | [diff] [blame] | 133 | } |
| 134 | } |
| 135 | benchHelper(b, *n, read) |
| 136 | } |
| 137 | |
| 138 | func benchHelper(b *testing.B, n int, read func(chan struct{})) { |
| 139 | m := make([]chan struct{}, n) |
| 140 | for i := range m { |
| 141 | m[i] = make(chan struct{}, 1) |
| 142 | go read(m[i]) |
| 143 | } |
| 144 | b.StopTimer() |
| 145 | b.ResetTimer() |
| 146 | GC() |
| 147 | |
| 148 | for i := 0; i < b.N; i++ { |
| 149 | for _, ch := range m { |
| 150 | if ch != nil { |
| 151 | ch <- struct{}{} |
| 152 | } |
| 153 | } |
| 154 | time.Sleep(10 * time.Millisecond) |
| 155 | b.StartTimer() |
| 156 | GC() |
| 157 | b.StopTimer() |
| 158 | } |
| 159 | |
| 160 | for _, ch := range m { |
| 161 | close(ch) |
| 162 | } |
| 163 | time.Sleep(10 * time.Millisecond) |
| 164 | } |
| 165 | |
| 166 | func BenchmarkGoroutineIdle(b *testing.B) { |
| 167 | quit := make(chan struct{}) |
| 168 | fn := func() { |
| 169 | <-quit |
| 170 | } |
| 171 | for i := 0; i < *n; i++ { |
| 172 | go fn() |
| 173 | } |
| 174 | |
| 175 | GC() |
| 176 | b.ResetTimer() |
| 177 | |
| 178 | for i := 0; i < b.N; i++ { |
| 179 | GC() |
| 180 | } |
| 181 | |
| 182 | b.StopTimer() |
| 183 | close(quit) |
| 184 | time.Sleep(10 * time.Millisecond) |
| 185 | } |