github.com/aloncn/graphics-go@v0.0.1/src/runtime/malloc_test.go (about) 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 ( 8 "flag" 9 . "runtime" 10 "testing" 11 "time" 12 "unsafe" 13 ) 14 15 func TestMemStats(t *testing.T) { 16 // Test that MemStats has sane values. 17 st := new(MemStats) 18 ReadMemStats(st) 19 20 // Everything except HeapReleased, HeapIdle, and NumGC, 21 // because they indeed can be 0. 22 if st.Alloc == 0 || st.TotalAlloc == 0 || st.Sys == 0 || st.Lookups == 0 || 23 st.Mallocs == 0 || st.Frees == 0 || st.HeapAlloc == 0 || st.HeapSys == 0 || 24 st.HeapInuse == 0 || st.HeapObjects == 0 || st.StackInuse == 0 || 25 st.StackSys == 0 || st.MSpanInuse == 0 || st.MSpanSys == 0 || st.MCacheInuse == 0 || 26 st.MCacheSys == 0 || st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 || 27 st.NextGC == 0 { 28 t.Fatalf("Zero value: %+v", *st) 29 } 30 31 if st.Alloc > 1e10 || st.TotalAlloc > 1e11 || st.Sys > 1e10 || st.Lookups > 1e10 || 32 st.Mallocs > 1e10 || st.Frees > 1e10 || st.HeapAlloc > 1e10 || st.HeapSys > 1e10 || 33 st.HeapIdle > 1e10 || st.HeapInuse > 1e10 || st.HeapObjects > 1e10 || st.StackInuse > 1e10 || 34 st.StackSys > 1e10 || st.MSpanInuse > 1e10 || st.MSpanSys > 1e10 || st.MCacheInuse > 1e10 || 35 st.MCacheSys > 1e10 || st.BuckHashSys > 1e10 || st.GCSys > 1e10 || st.OtherSys > 1e10 || 36 st.NextGC > 1e10 || st.NumGC > 1e9 || st.PauseTotalNs > 1e11 { 37 t.Fatalf("Insanely high value (overflow?): %+v", *st) 38 } 39 40 if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+ 41 st.BuckHashSys+st.GCSys+st.OtherSys { 42 t.Fatalf("Bad sys value: %+v", *st) 43 } 44 45 if st.HeapIdle+st.HeapInuse != st.HeapSys { 46 t.Fatalf("HeapIdle(%d) + HeapInuse(%d) should be equal to HeapSys(%d), but isn't.", st.HeapIdle, st.HeapInuse, st.HeapSys) 47 } 48 49 if lpe := st.PauseEnd[int(st.NumGC+255)%len(st.PauseEnd)]; st.LastGC != lpe { 50 t.Fatalf("LastGC(%d) != last PauseEnd(%d)", st.LastGC, lpe) 51 } 52 53 var pauseTotal uint64 54 for _, pause := range st.PauseNs { 55 pauseTotal += pause 56 } 57 if int(st.NumGC) < len(st.PauseNs) { 58 // We have all pauses, so this should be exact. 59 if st.PauseTotalNs != pauseTotal { 60 t.Fatalf("PauseTotalNs(%d) != sum PauseNs(%d)", st.PauseTotalNs, pauseTotal) 61 } 62 for i := int(st.NumGC); i < len(st.PauseNs); i++ { 63 if st.PauseNs[i] != 0 { 64 t.Fatalf("Non-zero PauseNs[%d]: %+v", i, st) 65 } 66 if st.PauseEnd[i] != 0 { 67 t.Fatalf("Non-zero PauseEnd[%d]: %+v", i, st) 68 } 69 } 70 } else { 71 if st.PauseTotalNs < pauseTotal { 72 t.Fatalf("PauseTotalNs(%d) < sum PauseNs(%d)", st.PauseTotalNs, pauseTotal) 73 } 74 } 75 } 76 77 func TestStringConcatenationAllocs(t *testing.T) { 78 n := testing.AllocsPerRun(1e3, func() { 79 b := make([]byte, 10) 80 for i := 0; i < 10; i++ { 81 b[i] = byte(i) + '0' 82 } 83 s := "foo" + string(b) 84 if want := "foo0123456789"; s != want { 85 t.Fatalf("want %v, got %v", want, s) 86 } 87 }) 88 // Only string concatenation allocates. 89 if n != 1 { 90 t.Fatalf("want 1 allocation, got %v", n) 91 } 92 } 93 94 func TestTinyAlloc(t *testing.T) { 95 const N = 16 96 var v [N]unsafe.Pointer 97 for i := range v { 98 v[i] = unsafe.Pointer(new(byte)) 99 } 100 101 chunks := make(map[uintptr]bool, N) 102 for _, p := range v { 103 chunks[uintptr(p)&^7] = true 104 } 105 106 if len(chunks) == N { 107 t.Fatal("no bytes allocated within the same 8-byte chunk") 108 } 109 } 110 111 var mallocSink uintptr 112 113 func BenchmarkMalloc8(b *testing.B) { 114 var x uintptr 115 for i := 0; i < b.N; i++ { 116 p := new(int64) 117 x ^= uintptr(unsafe.Pointer(p)) 118 } 119 mallocSink = x 120 } 121 122 func BenchmarkMalloc16(b *testing.B) { 123 var x uintptr 124 for i := 0; i < b.N; i++ { 125 p := new([2]int64) 126 x ^= uintptr(unsafe.Pointer(p)) 127 } 128 mallocSink = x 129 } 130 131 func BenchmarkMallocTypeInfo8(b *testing.B) { 132 var x uintptr 133 for i := 0; i < b.N; i++ { 134 p := new(struct { 135 p [8 / unsafe.Sizeof(uintptr(0))]*int 136 }) 137 x ^= uintptr(unsafe.Pointer(p)) 138 } 139 mallocSink = x 140 } 141 142 func BenchmarkMallocTypeInfo16(b *testing.B) { 143 var x uintptr 144 for i := 0; i < b.N; i++ { 145 p := new(struct { 146 p [16 / unsafe.Sizeof(uintptr(0))]*int 147 }) 148 x ^= uintptr(unsafe.Pointer(p)) 149 } 150 mallocSink = x 151 } 152 153 type LargeStruct struct { 154 x [16][]byte 155 } 156 157 func BenchmarkMallocLargeStruct(b *testing.B) { 158 var x uintptr 159 for i := 0; i < b.N; i++ { 160 p := make([]LargeStruct, 2) 161 x ^= uintptr(unsafe.Pointer(&p[0])) 162 } 163 mallocSink = x 164 } 165 166 var n = flag.Int("n", 1000, "number of goroutines") 167 168 func BenchmarkGoroutineSelect(b *testing.B) { 169 quit := make(chan struct{}) 170 read := func(ch chan struct{}) { 171 for { 172 select { 173 case _, ok := <-ch: 174 if !ok { 175 return 176 } 177 case <-quit: 178 return 179 } 180 } 181 } 182 benchHelper(b, *n, read) 183 } 184 185 func BenchmarkGoroutineBlocking(b *testing.B) { 186 read := func(ch chan struct{}) { 187 for { 188 if _, ok := <-ch; !ok { 189 return 190 } 191 } 192 } 193 benchHelper(b, *n, read) 194 } 195 196 func BenchmarkGoroutineForRange(b *testing.B) { 197 read := func(ch chan struct{}) { 198 for range ch { 199 } 200 } 201 benchHelper(b, *n, read) 202 } 203 204 func benchHelper(b *testing.B, n int, read func(chan struct{})) { 205 m := make([]chan struct{}, n) 206 for i := range m { 207 m[i] = make(chan struct{}, 1) 208 go read(m[i]) 209 } 210 b.StopTimer() 211 b.ResetTimer() 212 GC() 213 214 for i := 0; i < b.N; i++ { 215 for _, ch := range m { 216 if ch != nil { 217 ch <- struct{}{} 218 } 219 } 220 time.Sleep(10 * time.Millisecond) 221 b.StartTimer() 222 GC() 223 b.StopTimer() 224 } 225 226 for _, ch := range m { 227 close(ch) 228 } 229 time.Sleep(10 * time.Millisecond) 230 } 231 232 func BenchmarkGoroutineIdle(b *testing.B) { 233 quit := make(chan struct{}) 234 fn := func() { 235 <-quit 236 } 237 for i := 0; i < *n; i++ { 238 go fn() 239 } 240 241 GC() 242 b.ResetTimer() 243 244 for i := 0; i < b.N; i++ { 245 GC() 246 } 247 248 b.StopTimer() 249 close(quit) 250 time.Sleep(10 * time.Millisecond) 251 }