@@ -9,7 +9,6 @@ package main
9
9
import (
10
10
"bufio"
11
11
"fmt"
12
- "internal/trace"
13
12
"io"
14
13
"io/ioutil"
15
14
"net/http"
@@ -21,6 +20,8 @@ import (
21
20
"strconv"
22
21
"time"
23
22
23
+ trace "internal/traceparser"
24
+
24
25
"github.com/google/pprof/profile"
25
26
)
26
27
@@ -60,22 +61,22 @@ type interval struct {
60
61
begin , end int64 // nanoseconds.
61
62
}
62
63
63
- func pprofByGoroutine (compute func (io.Writer , map [uint64 ][]interval , [] * trace.Event ) error ) func (w io.Writer , r * http.Request ) error {
64
+ func pprofByGoroutine (compute func (io.Writer , map [uint64 ][]interval , * trace.Parsed ) error ) func (w io.Writer , r * http.Request ) error {
64
65
return func (w io.Writer , r * http.Request ) error {
65
66
id := r .FormValue ("id" )
66
- events , err := parseEvents ()
67
+ res , err := parseTrace ()
67
68
if err != nil {
68
69
return err
69
70
}
70
- gToIntervals , err := pprofMatchingGoroutines (id , events )
71
+ gToIntervals , err := pprofMatchingGoroutines (id , res )
71
72
if err != nil {
72
73
return err
73
74
}
74
- return compute (w , gToIntervals , events )
75
+ return compute (w , gToIntervals , res )
75
76
}
76
77
}
77
78
78
- func pprofByRegion (compute func (io.Writer , map [uint64 ][]interval , [] * trace.Event ) error ) func (w io.Writer , r * http.Request ) error {
79
+ func pprofByRegion (compute func (io.Writer , map [uint64 ][]interval , * trace.Parsed ) error ) func (w io.Writer , r * http.Request ) error {
79
80
return func (w io.Writer , r * http.Request ) error {
80
81
filter , err := newRegionFilter (r )
81
82
if err != nil {
@@ -85,7 +86,7 @@ func pprofByRegion(compute func(io.Writer, map[uint64][]interval, []*trace.Event
85
86
if err != nil {
86
87
return err
87
88
}
88
- events , _ := parseEvents ()
89
+ events , _ := parseTrace ()
89
90
90
91
return compute (w , gToIntervals , events )
91
92
}
@@ -94,15 +95,15 @@ func pprofByRegion(compute func(io.Writer, map[uint64][]interval, []*trace.Event
94
95
// pprofMatchingGoroutines parses the goroutine type id string (i.e. pc)
95
96
// and returns the ids of goroutines of the matching type and its interval.
96
97
// If the id string is empty, returns nil without an error.
97
- func pprofMatchingGoroutines (id string , events [] * trace.Event ) (map [uint64 ][]interval , error ) {
98
+ func pprofMatchingGoroutines (id string , p * trace.Parsed ) (map [uint64 ][]interval , error ) {
98
99
if id == "" {
99
100
return nil , nil
100
101
}
101
102
pc , err := strconv .ParseUint (id , 10 , 64 ) // id is string
102
103
if err != nil {
103
104
return nil , fmt .Errorf ("invalid goroutine type: %v" , id )
104
105
}
105
- analyzeGoroutines (events )
106
+ analyzeGoroutines (p )
106
107
var res map [uint64 ][]interval
107
108
for _ , g := range gs {
108
109
if g .PC != pc {
@@ -171,17 +172,25 @@ func pprofMatchingRegions(filter *regionFilter) (map[uint64][]interval, error) {
171
172
return gToIntervals , nil
172
173
}
173
174
175
+ func stklen (p * trace.Parsed , ev * trace.Event ) int {
176
+ if ev .StkID == 0 {
177
+ return 0
178
+ }
179
+ return len (p .Stacks [ev .StkID ])
180
+ }
181
+
174
182
// computePprofIO generates IO pprof-like profile (time spent in IO wait, currently only network blocking event).
175
- func computePprofIO (w io.Writer , gToIntervals map [uint64 ][]interval , events []* trace.Event ) error {
176
- prof := make (map [uint64 ]Record )
183
+ func computePprofIO (w io.Writer , gToIntervals map [uint64 ][]interval , res * trace.Parsed ) error {
184
+ events := res .Events
185
+ prof := make (map [uint32 ]Record )
177
186
for _ , ev := range events {
178
- if ev .Type != trace .EvGoBlockNet || ev .Link == nil || ev .StkID == 0 || len ( ev . Stk ) == 0 {
187
+ if ev .Type != trace .EvGoBlockNet || ev .Link == nil || ev .StkID == 0 || stklen ( res , ev ) == 0 {
179
188
continue
180
189
}
181
190
overlapping := pprofOverlappingDuration (gToIntervals , ev )
182
191
if overlapping > 0 {
183
192
rec := prof [ev .StkID ]
184
- rec .stk = ev .Stk
193
+ rec .stk = res . Stacks [ ev .StkID ]
185
194
rec .n ++
186
195
rec .time += overlapping .Nanoseconds ()
187
196
prof [ev .StkID ] = rec
@@ -191,8 +200,9 @@ func computePprofIO(w io.Writer, gToIntervals map[uint64][]interval, events []*t
191
200
}
192
201
193
202
// computePprofBlock generates blocking pprof-like profile (time spent blocked on synchronization primitives).
194
- func computePprofBlock (w io.Writer , gToIntervals map [uint64 ][]interval , events []* trace.Event ) error {
195
- prof := make (map [uint64 ]Record )
203
+ func computePprofBlock (w io.Writer , gToIntervals map [uint64 ][]interval , res * trace.Parsed ) error {
204
+ events := res .Events
205
+ prof := make (map [uint32 ]Record )
196
206
for _ , ev := range events {
197
207
switch ev .Type {
198
208
case trace .EvGoBlockSend , trace .EvGoBlockRecv , trace .EvGoBlockSelect ,
@@ -203,13 +213,13 @@ func computePprofBlock(w io.Writer, gToIntervals map[uint64][]interval, events [
203
213
default :
204
214
continue
205
215
}
206
- if ev .Link == nil || ev .StkID == 0 || len ( ev . Stk ) == 0 {
216
+ if ev .Link == nil || ev .StkID == 0 || stklen ( res , ev ) == 0 {
207
217
continue
208
218
}
209
219
overlapping := pprofOverlappingDuration (gToIntervals , ev )
210
220
if overlapping > 0 {
211
221
rec := prof [ev .StkID ]
212
- rec .stk = ev .Stk
222
+ rec .stk = res . Stacks [ ev .StkID ]
213
223
rec .n ++
214
224
rec .time += overlapping .Nanoseconds ()
215
225
prof [ev .StkID ] = rec
@@ -219,16 +229,17 @@ func computePprofBlock(w io.Writer, gToIntervals map[uint64][]interval, events [
219
229
}
220
230
221
231
// computePprofSyscall generates syscall pprof-like profile (time spent blocked in syscalls).
222
- func computePprofSyscall (w io.Writer , gToIntervals map [uint64 ][]interval , events []* trace.Event ) error {
223
- prof := make (map [uint64 ]Record )
232
+ func computePprofSyscall (w io.Writer , gToIntervals map [uint64 ][]interval , res * trace.Parsed ) error {
233
+ events := res .Events
234
+ prof := make (map [uint32 ]Record )
224
235
for _ , ev := range events {
225
- if ev .Type != trace .EvGoSysCall || ev .Link == nil || ev .StkID == 0 || len ( ev . Stk ) == 0 {
236
+ if ev .Type != trace .EvGoSysCall || ev .Link == nil || ev .StkID == 0 || stklen ( res , ev ) == 0 {
226
237
continue
227
238
}
228
239
overlapping := pprofOverlappingDuration (gToIntervals , ev )
229
240
if overlapping > 0 {
230
241
rec := prof [ev .StkID ]
231
- rec .stk = ev .Stk
242
+ rec .stk = res . Stacks [ ev .StkID ]
232
243
rec .n ++
233
244
rec .time += overlapping .Nanoseconds ()
234
245
prof [ev .StkID ] = rec
@@ -239,17 +250,18 @@ func computePprofSyscall(w io.Writer, gToIntervals map[uint64][]interval, events
239
250
240
251
// computePprofSched generates scheduler latency pprof-like profile
241
252
// (time between a goroutine become runnable and actually scheduled for execution).
242
- func computePprofSched (w io.Writer , gToIntervals map [uint64 ][]interval , events []* trace.Event ) error {
243
- prof := make (map [uint64 ]Record )
253
+ func computePprofSched (w io.Writer , gToIntervals map [uint64 ][]interval , res * trace.Parsed ) error {
254
+ events := res .Events
255
+ prof := make (map [uint32 ]Record )
244
256
for _ , ev := range events {
245
257
if (ev .Type != trace .EvGoUnblock && ev .Type != trace .EvGoCreate ) ||
246
- ev .Link == nil || ev .StkID == 0 || len ( ev . Stk ) == 0 {
258
+ ev .Link == nil || ev .StkID == 0 || stklen ( res , ev ) == 0 {
247
259
continue
248
260
}
249
261
overlapping := pprofOverlappingDuration (gToIntervals , ev )
250
262
if overlapping > 0 {
251
263
rec := prof [ev .StkID ]
252
- rec .stk = ev .Stk
264
+ rec .stk = res . Stacks [ ev .StkID ]
253
265
rec .n ++
254
266
rec .time += overlapping .Nanoseconds ()
255
267
prof [ev .StkID ] = rec
@@ -327,7 +339,7 @@ func serveSVGProfile(prof func(w io.Writer, r *http.Request) error) http.Handler
327
339
}
328
340
}
329
341
330
- func buildProfile (prof map [uint64 ]Record ) * profile.Profile {
342
+ func buildProfile (prof map [uint32 ]Record ) * profile.Profile {
331
343
p := & profile.Profile {
332
344
PeriodType : & profile.ValueType {Type : "trace" , Unit : "count" },
333
345
Period : 1 ,
0 commit comments