Source file src/pkg/cmd/compile/internal/gc/timings.go
1
2
3
4
5 package gc
6
7 import (
8 "fmt"
9 "io"
10 "strings"
11 "time"
12 )
13
14
15
16
17 type Timings struct {
18 list []timestamp
19 events map[int][]*event
20 }
21
22 type timestamp struct {
23 time time.Time
24 label string
25 start bool
26 }
27
28 type event struct {
29 size int64
30 unit string
31 }
32
33 func (t *Timings) append(labels []string, start bool) {
34 t.list = append(t.list, timestamp{time.Now(), strings.Join(labels, ":"), start})
35 }
36
37
38
39 func (t *Timings) Start(labels ...string) {
40 t.append(labels, true)
41 }
42
43
44
45 func (t *Timings) Stop(labels ...string) {
46 t.append(labels, false)
47 }
48
49
50
51
52
53 func (t *Timings) AddEvent(size int64, unit string) {
54 m := t.events
55 if m == nil {
56 m = make(map[int][]*event)
57 t.events = m
58 }
59 i := len(t.list)
60 if i > 0 {
61 i--
62 }
63 m[i] = append(m[i], &event{size, unit})
64 }
65
66
67
68 func (t *Timings) Write(w io.Writer, prefix string) {
69 if len(t.list) > 0 {
70 var lines lines
71
72
73 var group struct {
74 label string
75 tot time.Duration
76 size int
77 }
78
79
80 var unaccounted time.Duration
81
82
83 pt := &t.list[0]
84 tot := t.list[len(t.list)-1].time.Sub(pt.time)
85 for i := 1; i < len(t.list); i++ {
86 qt := &t.list[i]
87 dt := qt.time.Sub(pt.time)
88
89 var label string
90 var events []*event
91 if pt.start {
92
93 label = pt.label
94 events = t.events[i-1]
95 if qt.start {
96
97 } else {
98
99 if qt.label != "" {
100 label += ":" + qt.label
101 }
102
103 if e := t.events[i]; e != nil {
104 events = e
105 }
106 }
107 } else {
108
109 if qt.start {
110
111 unaccounted += dt
112 } else {
113
114 label = qt.label
115 events = t.events[i]
116 }
117 }
118 if label != "" {
119
120 l := commonPrefix(group.label, label)
121 if group.size == 1 && l != "" || group.size > 1 && l == group.label {
122
123 group.label = l
124 group.tot += dt
125 group.size++
126 } else {
127
128 if group.size > 1 {
129 lines.add(prefix+group.label+"subtotal", 1, group.tot, tot, nil)
130 }
131 group.label = label
132 group.tot = dt
133 group.size = 1
134 }
135
136
137 lines.add(prefix+label, 1, dt, tot, events)
138 }
139
140 pt = qt
141 }
142
143 if group.size > 1 {
144 lines.add(prefix+group.label+"subtotal", 1, group.tot, tot, nil)
145 }
146
147 if unaccounted != 0 {
148 lines.add(prefix+"unaccounted", 1, unaccounted, tot, nil)
149 }
150
151 lines.add(prefix+"total", 1, tot, tot, nil)
152
153 lines.write(w)
154 }
155 }
156
157 func commonPrefix(a, b string) string {
158 i := 0
159 for i < len(a) && i < len(b) && a[i] == b[i] {
160 i++
161 }
162 return a[:i]
163 }
164
165 type lines [][]string
166
167 func (lines *lines) add(label string, n int, dt, tot time.Duration, events []*event) {
168 var line []string
169 add := func(format string, args ...interface{}) {
170 line = append(line, fmt.Sprintf(format, args...))
171 }
172
173 add("%s", label)
174 add(" %d", n)
175 add(" %d ns/op", dt)
176 add(" %.2f %%", float64(dt)/float64(tot)*100)
177
178 for _, e := range events {
179 add(" %d", e.size)
180 add(" %s", e.unit)
181 add(" %d", int64(float64(e.size)/dt.Seconds()+0.5))
182 add(" %s/s", e.unit)
183 }
184
185 *lines = append(*lines, line)
186 }
187
188 func (lines lines) write(w io.Writer) {
189
190 var widths []int
191 var number []bool
192 for _, line := range lines {
193 for i, col := range line {
194 if i < len(widths) {
195 if len(col) > widths[i] {
196 widths[i] = len(col)
197 }
198 } else {
199 widths = append(widths, len(col))
200 number = append(number, isnumber(col))
201 }
202 }
203 }
204
205
206 const align = 1
207 if align > 1 {
208 for i, w := range widths {
209 w += align - 1
210 widths[i] = w - w%align
211 }
212 }
213
214
215 for _, line := range lines {
216 for i, col := range line {
217 format := "%-*s"
218 if number[i] {
219 format = "%*s"
220 }
221 fmt.Fprintf(w, format, widths[i], col)
222 }
223 fmt.Fprintln(w)
224 }
225 }
226
227 func isnumber(s string) bool {
228 for _, ch := range s {
229 if ch <= ' ' {
230 continue
231 }
232 return '0' <= ch && ch <= '9' || ch == '.' || ch == '-' || ch == '+'
233 }
234 return false
235 }
236
View as plain text