...
1
2
3
4
5
6
7 package pprof
8
9 import (
10 "fmt"
11 "time"
12 )
13
14
15
16 func TotalTime(data []byte) (total time.Duration, err error) {
17 defer func() {
18 if x := recover(); x != nil {
19 err = fmt.Errorf("error parsing pprof profile: %v", x)
20 }
21 }()
22 decode(&total, data, msgProfile)
23 return
24 }
25
26
27
28
29
30 const (
31 wireVarint = 0
32 wireBytes = 2
33 )
34
35
36 const (
37 fldProfileSample = 2
38 fldSampleValue = 2
39 )
40
41
42 const (
43 msgProfile = 0
44 msgSample = 1
45 )
46
47 func decode(total *time.Duration, data []byte, msg int) {
48 for len(data) > 0 {
49
50 tag := varint(&data)
51
52
53 wire := tag & 7
54 var ival uint64
55 var sval []byte
56 switch wire {
57 case wireVarint:
58 ival = varint(&data)
59
60 case wireBytes:
61 n := varint(&data)
62 sval, data = data[:n], data[n:]
63
64 default:
65 panic(fmt.Sprintf("unexpected wire type: %d", wire))
66 }
67
68
69 fld := tag >> 3
70 switch {
71 case msg == msgProfile && fld == fldProfileSample:
72 decode(total, sval, msgSample)
73
74 case msg == msgSample, fld == fldSampleValue:
75 *total += time.Duration(ival)
76 }
77 }
78 }
79
80 func varint(data *[]byte) (v uint64) {
81 for i := 0; ; i++ {
82 b := uint64((*data)[i])
83 v += (b & 0x7f) << (7 * i)
84 if b < 0x80 {
85 *data = (*data)[i+1:]
86 return v
87 }
88 }
89 }
90
View as plain text