-
Notifications
You must be signed in to change notification settings - Fork 0
/
analysis.go
119 lines (105 loc) · 2.58 KB
/
analysis.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package analysis
import (
"fmt"
"log"
"regexp"
"strings"
"github.com/jedib0t/go-pretty/text"
"github.com/jedib0t/go-pretty/table"
)
// Variable is the struct storing the variable should be stored in heap or struct
// according to the escape analysis
type Variable struct {
Stacks []string
Heaps []string
}
// Analysis is the struct storing analysis results.
type Analysis struct {
PathRgx *regexp.Regexp
StackRgx []*regexp.Regexp
HeapRgx []*regexp.Regexp
Codes []string
Result map[string]*Variable
}
// New returns Analysis initialized with path regexp.
func New() *Analysis {
r, err := regexp.Compile(`^(.*):\d+:\d+`)
if err != nil {
log.Fatalf("regex failure %s\n", err)
return nil
}
hr1, _ := regexp.Compile(`:[[:space:]](.*) escapes to heap$`)
hr2, _ := regexp.Compile(`moved to heap:[[:space:]](.*)$`)
sr1, _ := regexp.Compile(`:[[:space:]](.*) does not escape$`)
return &Analysis{
PathRgx: r,
HeapRgx: []*regexp.Regexp{hr1, hr2},
StackRgx: []*regexp.Regexp{sr1},
Result: make(map[string]*Variable),
}
}
// Start starts parsing escape analysis of the output of go build -gcflags=-m
func (a *Analysis) Start(data string) {
s := strings.Split(data, "\n")
for _, val := range s {
if a.PathRgx.MatchString(val) {
path := a.PathRgx.FindStringSubmatch(val)[0]
for _, stck := range a.StackRgx {
if stck.MatchString(val) {
v, ok := a.Result[path]
if !ok {
v = &Variable{
Stacks: nil,
Heaps: nil,
}
a.Codes = append(a.Codes, path)
}
v.Stacks = append(v.Stacks, stck.FindStringSubmatch(val)[1])
a.Result[path] = v
continue
}
}
for _, heap := range a.HeapRgx {
if heap.MatchString(val) {
v, ok := a.Result[path]
if !ok {
v = &Variable{
Stacks: nil,
Heaps: nil,
}
a.Codes = append(a.Codes, path)
}
v.Heaps = append(v.Heaps, heap.FindStringSubmatch(val)[1])
a.Result[path] = v
continue
}
}
}
}
}
func (a *Analysis) String() string {
tw := table.NewWriter()
tw.SetTitle("GOESP")
tw.AppendHeader(table.Row{"CODE", "STACK", "HEAP"})
var ts []table.Row
for _, code := range a.Codes {
var strS string
stcks := a.Result[code].Stacks
for _, s := range stcks {
strS += fmt.Sprintf("%s,", s)
}
var heapS string
heaps := a.Result[code].Heaps
for _, h := range heaps {
heapS += fmt.Sprintf("%s,", h)
}
ts = append(ts, table.Row{
code, strS, heapS,
})
}
tw.AppendRows(ts)
tw.SetStyle(table.StyleBold)
tw.Style().Title.Align = text.AlignCenter
tw.Style().Options.SeparateRows = true
return tw.Render()
}