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.
17 var memSink
interface{}
19 func allocateTransient1M() {
20 for i
:= 0; i
< 1024; i
++ {
21 memSink
= &struct{ x
[1024]byte }{}
26 func allocateTransient2M() {
27 memSink
= make([]byte, 2<<20)
32 pad
[32 - unsafe
.Sizeof(uintptr(0))]byte
35 var persistentMemSink
*Obj32
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
45 // Allocate transient memory using reflect.Call.
47 func allocateReflectTransient() {
48 memSink
= make([]byte, 2<<20)
51 func allocateReflect() {
52 rv
:= reflect
.ValueOf(allocateReflectTransient
)
56 var memoryProfilerRun
= 0
58 func TestMemoryProfiler(t
*testing
.T
) {
59 // Disable sampling, otherwise it's difficult to assert anything.
60 oldRate
:= runtime
.MemProfileRate
61 runtime
.MemProfileRate
= 1
63 runtime
.MemProfileRate
= oldRate
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)
71 // Do the interesting allocations.
74 allocatePersistent1K()
78 runtime
.GC() // materialize stats
80 if err
:= Lookup("heap").WriteTo(&buf
, 1); err
!= nil {
81 t
.Fatalf("failed to write heap profile: %v", err
)
88 fmt
.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+
89 # 0x[0-9,a-f]+ pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:40
90 # 0x[0-9,a-f]+ runtime_pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:74
91 `, 32*memoryProfilerRun
, 1024*memoryProfilerRun
, 32*memoryProfilerRun
, 1024*memoryProfilerRun
),
93 fmt
.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f x]+
94 # 0x[0-9,a-f]+ pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:21
95 # 0x[0-9,a-f]+ runtime_pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:72
96 `, (1<<10)*memoryProfilerRun
, (1<<20)*memoryProfilerRun
),
98 // This should start with "0: 0" but gccgo's imprecise
99 // GC means that sometimes the value is not collected.
100 fmt
.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
101 # 0x[0-9,a-f]+ pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:27
102 # 0x[0-9,a-f]+ runtime_pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:73
103 `, memoryProfilerRun
, (2<<20)*memoryProfilerRun
, memoryProfilerRun
, (2<<20)*memoryProfilerRun
),
105 // This should start with "0: 0" but gccgo's imprecise
106 // GC means that sometimes the value is not collected.
107 fmt
.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @( 0x[0-9,a-f]+)+
108 # 0x[0-9,a-f]+ pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/mprof_test.go:48
109 `, memoryProfilerRun
, (2<<20)*memoryProfilerRun
, memoryProfilerRun
, (2<<20)*memoryProfilerRun
),
112 for _
, test
:= range tests
{
113 if !regexp
.MustCompile(test
).Match(buf
.Bytes()) {
114 t
.Fatalf("The entry did not match:\n%v\n\nProfile:\n%v\n", test
, buf
.String())