1
2
3
4
5
6
7
8
9 package trace
10
11 import (
12 "cmp"
13 "encoding/binary"
14 "fmt"
15
16 "golang.org/x/exp/trace/internal/event"
17 "golang.org/x/exp/trace/internal/event/go122"
18 )
19
20 type batchCursor struct {
21 m ThreadID
22 lastTs Time
23 idx int
24 dataOff int
25 ev baseEvent
26 }
27
28 func (b *batchCursor) nextEvent(batches []batch, freq frequency) (ok bool, err error) {
29
30
31 for b.idx < len(batches) && len(batches[b.idx].data) == b.dataOff {
32 b.idx++
33 b.dataOff = 0
34 b.lastTs = 0
35 }
36
37 if b.idx == len(batches) {
38 return false, nil
39 }
40
41 if b.lastTs == 0 {
42 b.lastTs = freq.mul(batches[b.idx].time)
43 }
44
45 n, tsdiff, err := readTimedBaseEvent(batches[b.idx].data[b.dataOff:], &b.ev)
46 if err != nil {
47 return false, err
48 }
49
50 b.ev.time = freq.mul(tsdiff) + b.lastTs
51
52
53 b.lastTs = b.ev.time
54
55
56 b.dataOff += n
57 return true, nil
58 }
59
60 func (b *batchCursor) compare(a *batchCursor) int {
61 return cmp.Compare(b.ev.time, a.ev.time)
62 }
63
64
65
66
67
68
69
70
71 func readTimedBaseEvent(b []byte, e *baseEvent) (int, timestamp, error) {
72
73 typ := event.Type(b[0])
74 specs := go122.Specs()
75 if int(typ) >= len(specs) {
76 return 0, 0, fmt.Errorf("found invalid event type: %v", typ)
77 }
78 e.typ = typ
79
80
81 spec := &specs[typ]
82 if len(spec.Args) == 0 || !spec.IsTimedEvent {
83 return 0, 0, fmt.Errorf("found event without a timestamp: type=%v", typ)
84 }
85 n := 1
86
87
88 ts, nb := binary.Uvarint(b[n:])
89 if nb <= 0 {
90 return 0, 0, fmt.Errorf("found invalid uvarint for timestamp")
91 }
92 n += nb
93
94
95 for i := 0; i < len(spec.Args)-1; i++ {
96 arg, nb := binary.Uvarint(b[n:])
97 if nb <= 0 {
98 return 0, 0, fmt.Errorf("found invalid uvarint")
99 }
100 e.args[i] = arg
101 n += nb
102 }
103 return n, timestamp(ts), nil
104 }
105
106 func heapInsert(heap []*batchCursor, bc *batchCursor) []*batchCursor {
107
108 heap = append(heap, bc)
109
110
111 heapSiftUp(heap, len(heap)-1)
112 return heap
113 }
114
115 func heapUpdate(heap []*batchCursor, i int) {
116
117 if heapSiftUp(heap, i) != i {
118 return
119 }
120
121 heapSiftDown(heap, i)
122 }
123
124 func heapRemove(heap []*batchCursor, i int) []*batchCursor {
125
126 for i > 0 {
127 heap[(i-1)/2], heap[i] = heap[i], heap[(i-1)/2]
128 i = (i - 1) / 2
129 }
130
131 heap[0], heap[len(heap)-1] = heap[len(heap)-1], heap[0]
132 heap = heap[:len(heap)-1]
133
134 heapSiftDown(heap, 0)
135 return heap
136 }
137
138 func heapSiftUp(heap []*batchCursor, i int) int {
139 for i > 0 && heap[(i-1)/2].ev.time > heap[i].ev.time {
140 heap[(i-1)/2], heap[i] = heap[i], heap[(i-1)/2]
141 i = (i - 1) / 2
142 }
143 return i
144 }
145
146 func heapSiftDown(heap []*batchCursor, i int) int {
147 for {
148 m := min3(heap, i, 2*i+1, 2*i+2)
149 if m == i {
150
151 break
152 }
153 heap[i], heap[m] = heap[m], heap[i]
154 i = m
155 }
156 return i
157 }
158
159 func min3(b []*batchCursor, i0, i1, i2 int) int {
160 minIdx := i0
161 minT := maxTime
162 if i0 < len(b) {
163 minT = b[i0].ev.time
164 }
165 if i1 < len(b) {
166 if t := b[i1].ev.time; t < minT {
167 minT = t
168 minIdx = i1
169 }
170 }
171 if i2 < len(b) {
172 if t := b[i2].ev.time; t < minT {
173 minT = t
174 minIdx = i2
175 }
176 }
177 return minIdx
178 }
179
View as plain text