github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/runtime/pprof/mprof_test.go (about) 1 // Copyright 2014 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 pprof 6 7 import ( 8 "bytes" 9 "fmt" 10 "reflect" 11 "regexp" 12 "runtime" 13 "testing" 14 "unsafe" 15 ) 16 17 var memSink interface{} 18 19 func allocateTransient1M() { 20 for i := 0; i < 1024; i++ { 21 memSink = &struct{ x [1024]byte }{} 22 } 23 } 24 25 //go:noinline 26 func allocateTransient2M() { 27 memSink = make([]byte, 2<<20) 28 } 29 30 type Obj32 struct { 31 link *Obj32 32 pad [32 - unsafe.Sizeof(uintptr(0))]byte 33 } 34 35 var persistentMemSink *Obj32 36 37 func allocatePersistent1K() { 38 for i := 0; i < 32; i++ { 39 // Can't use slice because that will introduce implicit allocations. 40 obj := &Obj32{link: persistentMemSink} 41 persistentMemSink = obj 42 } 43 } 44 45 // Allocate transient memory using reflect.Call. 46 47 func allocateReflectTransient() { 48 memSink = make([]byte, 2<<20) 49 } 50 51 func allocateReflect() { 52 rv := reflect.ValueOf(allocateReflectTransient) 53 rv.Call(nil) 54 } 55 56 var memoryProfilerRun = 0 57 58 func TestMemoryProfiler(t *testing.T) { 59 // Disable sampling, otherwise it's difficult to assert anything. 60 oldRate := runtime.MemProfileRate 61 runtime.MemProfileRate = 1 62 defer func() { 63 runtime.MemProfileRate = oldRate 64 }() 65 66 // Allocate a meg to ensure that mcache.next_sample is updated to 1. 67 for i := 0; i < 1024; i++ { 68 memSink = make([]byte, 1024) 69 } 70 71 // Do the interesting allocations. 72 allocateTransient1M() 73 allocateTransient2M() 74 allocatePersistent1K() 75 allocateReflect() 76 memSink = nil 77 78 runtime.GC() // materialize stats 79 var buf bytes.Buffer 80 if err := Lookup("heap").WriteTo(&buf, 1); err != nil { 81 t.Fatalf("failed to write heap profile: %v", err) 82 } 83 84 memoryProfilerRun++ 85 86 tests := []string{ 87 fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 88 # 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:40 89 # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:74 90 `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun), 91 92 fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 93 # 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:21 94 # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:72 95 `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun), 96 97 fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 98 # 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:27 99 # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:73 100 `, memoryProfilerRun, (2<<20)*memoryProfilerRun), 101 102 fmt.Sprintf(`0: 0 \[%v: %v\] @( 0x[0-9,a-f]+)+ 103 # 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:48 104 `, memoryProfilerRun, (2<<20)*memoryProfilerRun), 105 } 106 107 for _, test := range tests { 108 if !regexp.MustCompile(test).Match(buf.Bytes()) { 109 t.Fatalf("The entry did not match:\n%v\n\nProfile:\n%v\n", test, buf.String()) 110 } 111 } 112 }