2
2
// Use of this source code is governed by a BSD-style
3
3
// license that can be found in the LICENSE file.
4
4
5
+ // +build !js
6
+
5
7
package pprof
6
8
7
9
import (
@@ -10,6 +12,7 @@ import (
10
12
"reflect"
11
13
"regexp"
12
14
"runtime"
15
+ "runtime/pprof/internal/profile"
13
16
"testing"
14
17
"unsafe"
15
18
)
@@ -27,6 +30,10 @@ func allocateTransient2M() {
27
30
memSink = make ([]byte , 2 << 20 )
28
31
}
29
32
33
+ func allocateTransient2MInline () {
34
+ memSink = make ([]byte , 2 << 20 )
35
+ }
36
+
30
37
type Obj32 struct {
31
38
link * Obj32
32
39
pad [32 - unsafe .Sizeof (uintptr (0 ))]byte
@@ -71,42 +78,93 @@ func TestMemoryProfiler(t *testing.T) {
71
78
// Do the interesting allocations.
72
79
allocateTransient1M ()
73
80
allocateTransient2M ()
81
+ allocateTransient2MInline ()
74
82
allocatePersistent1K ()
75
83
allocateReflect ()
76
84
memSink = nil
77
85
78
86
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
87
84
88
memoryProfilerRun ++
85
89
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
+ tests := []struct {
91
+ stk []string
92
+ legacy string
93
+ }{{
94
+ stk : []string {"runtime/pprof.allocatePersistent1K" , "runtime/pprof.TestMemoryProfiler" },
95
+ legacy : 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]+
96
+ # 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:47
97
+ # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:82
90
98
` , 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
99
+ }, {
100
+ stk : []string {"runtime/pprof.allocateTransient1M" , "runtime/pprof.TestMemoryProfiler" },
101
+ legacy : 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]+
102
+ # 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:24
103
+ # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:79
95
104
` , (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
105
+ }, {
106
+ stk : []string {"runtime/pprof.allocateTransient2M" , "runtime/pprof.TestMemoryProfiler" },
107
+ legacy : 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]+
108
+ # 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:30
109
+ # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:80
100
110
` , 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
111
+ }, {
112
+ stk : []string {"runtime/pprof.allocateTransient2MInline" , "runtime/pprof.TestMemoryProfiler" },
113
+ legacy : 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]+
114
+ # 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:34
115
+ # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:81
104
116
` , memoryProfilerRun , (2 << 20 )* memoryProfilerRun ),
105
- }
117
+ }, {
118
+ stk : []string {"runtime/pprof.allocateReflectTransient" },
119
+ legacy : fmt .Sprintf (`0: 0 \[%v: %v\] @( 0x[0-9,a-f]+)+
120
+ # 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:55
121
+ ` , memoryProfilerRun , (2 << 20 )* memoryProfilerRun ),
122
+ }}
106
123
107
- for _ , test := range tests {
108
- if ! regexp .MustCompile (test ).Match (buf .Bytes ()) {
109
- t .Fatalf ("The entry did not match:\n %v\n \n Profile:\n %v\n " , test , buf .String ())
124
+ t .Run ("debug=1" , func (t * testing.T ) {
125
+ var buf bytes.Buffer
126
+ if err := Lookup ("heap" ).WriteTo (& buf , 1 ); err != nil {
127
+ t .Fatalf ("failed to write heap profile: %v" , err )
110
128
}
111
- }
129
+
130
+ for _ , test := range tests {
131
+ if ! regexp .MustCompile (test .legacy ).Match (buf .Bytes ()) {
132
+ t .Fatalf ("The entry did not match:\n %v\n \n Profile:\n %v\n " , test .legacy , buf .String ())
133
+ }
134
+ }
135
+ })
136
+
137
+ t .Run ("proto" , func (t * testing.T ) {
138
+ var buf bytes.Buffer
139
+ if err := Lookup ("heap" ).WriteTo (& buf , 0 ); err != nil {
140
+ t .Fatalf ("failed to write heap profile: %v" , err )
141
+ }
142
+ p , err := profile .Parse (& buf )
143
+ if err != nil {
144
+ t .Fatalf ("failed to parse heap profile: %v" , err )
145
+ }
146
+ t .Logf ("Profile = %v" , p )
147
+
148
+ stks := stacks (p )
149
+ for _ , test := range tests {
150
+ if ! containsStack (stks , test .stk ) {
151
+ t .Fatalf ("No matching stack entry for %q\n \n Profile:\n %v\n " , test .stk , p )
152
+ }
153
+ }
154
+ // Check the inlined function location is encoded correctly.
155
+ for _ , loc := range p .Location {
156
+ inlinedCaller , inlinedCallee := false , false
157
+ for _ , line := range loc .Line {
158
+ if line .Function .Name == "runtime/pprof.allocateTransient2MInline" {
159
+ inlinedCallee = true
160
+ }
161
+ if inlinedCallee && line .Function .Name == "runtime/pprof.TestMemoryProfiler" {
162
+ inlinedCaller = true
163
+ }
164
+ }
165
+ if inlinedCallee != inlinedCaller {
166
+ t .Errorf ("want allocateTransient2MInline after TestMemoryProfiler in one location, got separate location entries:\n %v" , loc )
167
+ }
168
+ }
169
+ })
112
170
}
0 commit comments