-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsummary.go
79 lines (67 loc) · 1.67 KB
/
summary.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package main
import (
"bytes"
"fmt"
"log"
"time"
"loov.dev/allocview/internal/series"
"loov.dev/allocview/internal/symbols"
)
type Summary struct {
Config Config
Symbols *symbols.Binary
Collection *series.Collection3
}
func NewSummary(config Config) *Summary {
return &Summary{
Config: config,
Collection: series.NewCollection3(time.Now(), config.SampleDuration, config.SampleCount),
}
}
// Add adds profile to the collections.
func (summary *Summary) Add(profile *Profile) {
// TODO: per binary symbols
if summary.Symbols == nil {
// TODO: is there a better location to do this?
var err error
summary.Symbols, err = symbols.Load(profile.ExeName)
if err != nil {
log.Fatal(err)
}
summary.Symbols.UpdateOffset(profile.FuncName, profile.FuncAddr)
}
collection := summary.Collection
index := collection.UpdateToTime(profile.Time)
for i := range profile.Records {
rec := &profile.Records[i]
for i, frame := range rec.Stack0 {
if frame == 0 {
break
}
rec.Stack0[i] = uintptr(int64(frame) + summary.Symbols.Offset)
}
// TODO: implement skip runtime
collection.UpdateSample(index, rec.Stack0[:], series.Sample{
AllocBytes: rec.AllocBytes,
FreeBytes: rec.FreeBytes,
AllocObjects: rec.AllocObjects,
FreeObjects: rec.FreeObjects,
})
}
// TODO: reuse profile allocation
}
func (summary *Summary) StackAsString(stack []uintptr) string {
var s bytes.Buffer
for _, frame := range stack {
if frame == 0 {
break
}
file, line, _ := summary.Symbols.SymTable.PCToLine(uint64(frame))
if file == "" {
fmt.Fprintf(&s, "0x%x\n", frame)
continue
}
fmt.Fprintf(&s, "%s:%v\n", file, line)
}
return s.String()
}