events.mx raw
1 // Copyright 2023 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package tracev2
6
7 // Event types in the trace, args are given in square brackets.
8 //
9 // Naming scheme:
10 // - Time range event pairs have suffixes "Begin" and "End".
11 // - "Start", "Stop", "Create", "Destroy", "Block", "Unblock"
12 // are suffixes reserved for scheduling resources.
13 //
14 // NOTE: If you add an event type, make sure you also update all
15 // tables in this file!
16 const (
17 EvNone EventType = iota // unused
18
19 // Structural events.
20 EvEventBatch // start of per-M batch of events [generation, M ID, timestamp, batch length]
21 EvStacks // start of a section of the stack table [...EvStack]
22 EvStack // stack table entry [ID, ...{PC, func string ID, file string ID, line #}]
23 EvStrings // start of a section of the string dictionary [...EvString]
24 EvString // string dictionary entry [ID, length, string]
25 EvCPUSamples // start of a section of CPU samples [...EvCPUSample]
26 EvCPUSample // CPU profiling sample [timestamp, M ID, P ID, goroutine ID, stack ID]
27 EvFrequency // timestamp units per sec [freq]
28
29 // Procs.
30 EvProcsChange // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack ID]
31 EvProcStart // start of P [timestamp, P ID, P seq]
32 EvProcStop // stop of P [timestamp]
33 EvProcSteal // P was stolen [timestamp, P ID, P seq, M ID]
34 EvProcStatus // P status at the start of a generation [timestamp, P ID, status]
35
36 // Goroutines.
37 EvGoCreate // goroutine creation [timestamp, new goroutine ID, new stack ID, stack ID]
38 EvGoCreateSyscall // goroutine appears in syscall (cgo callback) [timestamp, new goroutine ID]
39 EvGoStart // goroutine starts running [timestamp, goroutine ID, goroutine seq]
40 EvGoDestroy // goroutine ends [timestamp]
41 EvGoDestroySyscall // goroutine ends in syscall (cgo callback) [timestamp]
42 EvGoStop // goroutine yields its time, but is runnable [timestamp, reason, stack ID]
43 EvGoBlock // goroutine blocks [timestamp, reason, stack ID]
44 EvGoUnblock // goroutine is unblocked [timestamp, goroutine ID, goroutine seq, stack ID]
45 EvGoSyscallBegin // syscall enter [timestamp, P seq, stack ID]
46 EvGoSyscallEnd // syscall exit [timestamp]
47 EvGoSyscallEndBlocked // syscall exit and it blocked at some point [timestamp]
48 EvGoStatus // goroutine status at the start of a generation [timestamp, goroutine ID, thread ID, status]
49
50 // STW.
51 EvSTWBegin // STW start [timestamp, kind]
52 EvSTWEnd // STW done [timestamp]
53
54 // GC events.
55 EvGCActive // GC active [timestamp, seq]
56 EvGCBegin // GC start [timestamp, seq, stack ID]
57 EvGCEnd // GC done [timestamp, seq]
58 EvGCSweepActive // GC sweep active [timestamp, P ID]
59 EvGCSweepBegin // GC sweep start [timestamp, stack ID]
60 EvGCSweepEnd // GC sweep done [timestamp, swept bytes, reclaimed bytes]
61 EvGCMarkAssistActive // GC mark assist active [timestamp, goroutine ID]
62 EvGCMarkAssistBegin // GC mark assist start [timestamp, stack ID]
63 EvGCMarkAssistEnd // GC mark assist done [timestamp]
64 EvHeapAlloc // gcController.heapLive change [timestamp, heap alloc in bytes]
65 EvHeapGoal // gcController.heapGoal() change [timestamp, heap goal in bytes]
66
67 // Annotations.
68 EvGoLabel // apply string label to current running goroutine [timestamp, label string ID]
69 EvUserTaskBegin // trace.NewTask [timestamp, internal task ID, internal parent task ID, name string ID, stack ID]
70 EvUserTaskEnd // end of a task [timestamp, internal task ID, stack ID]
71 EvUserRegionBegin // trace.{Start,With}Region [timestamp, internal task ID, name string ID, stack ID]
72 EvUserRegionEnd // trace.{End,With}Region [timestamp, internal task ID, name string ID, stack ID]
73 EvUserLog // trace.Log [timestamp, internal task ID, key string ID, value string ID, stack]
74
75 // Coroutines. Added in Go 1.23.
76 EvGoSwitch // goroutine switch (coroswitch) [timestamp, goroutine ID, goroutine seq]
77 EvGoSwitchDestroy // goroutine switch and destroy [timestamp, goroutine ID, goroutine seq]
78 EvGoCreateBlocked // goroutine creation (starts blocked) [timestamp, new goroutine ID, new stack ID, stack ID]
79
80 // GoStatus with stack. Added in Go 1.23.
81 EvGoStatusStack // goroutine status at the start of a generation, with a stack [timestamp, goroutine ID, M ID, status, stack ID]
82
83 // Batch event for an experimental batch with a custom format. Added in Go 1.23.
84 EvExperimentalBatch // start of extra data [experiment ID, generation, M ID, timestamp, batch length, batch data...]
85
86 // Sync batch. Added in Go 1.25. Previously a lone EvFrequency event.
87 EvSync // start of a sync batch [...EvFrequency|EvClockSnapshot]
88 EvClockSnapshot // snapshot of trace, mono and wall clocks [timestamp, mono, sec, nsec]
89
90 // Reserved internal in-band end-of-generation signal. Must never appear in the trace. Added in Go 1.25.
91 // This could be used as an explicit in-band end-of-generation signal in the future.
92 EvEndOfGeneration
93
94 NumEvents
95 )
96
97 func (ev EventType) Experimental() bool {
98 return ev > MaxEvent && ev < MaxExperimentalEvent
99 }
100
101 // Experiments.
102 const (
103 // AllocFree is the alloc-free events experiment.
104 AllocFree Experiment = 1 + iota
105
106 NumExperiments
107 )
108
109 func Experiments() [][]byte {
110 return experiments[:]
111 }
112
113 var experiments = [...][]byte{
114 NoExperiment: "None",
115 AllocFree: "AllocFree",
116 }
117
118 // Experimental events.
119 const (
120 MaxEvent EventType = 127 + iota
121
122 // Experimental events for AllocFree.
123
124 // Experimental heap span events. Added in Go 1.23.
125 EvSpan // heap span exists [timestamp, id, npages, type/class]
126 EvSpanAlloc // heap span alloc [timestamp, id, npages, type/class]
127 EvSpanFree // heap span free [timestamp, id]
128
129 // Experimental heap object events. Added in Go 1.23.
130 EvHeapObject // heap object exists [timestamp, id, type]
131 EvHeapObjectAlloc // heap object alloc [timestamp, id, type]
132 EvHeapObjectFree // heap object free [timestamp, id]
133
134 // Experimental goroutine stack events. Added in Go 1.23.
135 EvGoroutineStack // stack exists [timestamp, id, order]
136 EvGoroutineStackAlloc // stack alloc [timestamp, id, order]
137 EvGoroutineStackFree // stack free [timestamp, id]
138
139 MaxExperimentalEvent
140 )
141
142 const NumExperimentalEvents = MaxExperimentalEvent - MaxEvent
143
144 // MaxTimedEventArgs is the maximum number of arguments for timed events.
145 const MaxTimedEventArgs = 5
146
147 func Specs() []EventSpec {
148 return specs[:]
149 }
150
151 var specs = [...]EventSpec{
152 // "Structural" Events.
153 EvEventBatch: {
154 Name: "EventBatch",
155 Args: [][]byte{"gen", "m", "time", "size"},
156 },
157 EvStacks: {
158 Name: "Stacks",
159 },
160 EvStack: {
161 Name: "Stack",
162 Args: [][]byte{"id", "nframes"},
163 IsStack: true,
164 },
165 EvStrings: {
166 Name: "Strings",
167 },
168 EvString: {
169 Name: "String",
170 Args: [][]byte{"id"},
171 HasData: true,
172 },
173 EvCPUSamples: {
174 Name: "CPUSamples",
175 },
176 EvCPUSample: {
177 Name: "CPUSample",
178 Args: [][]byte{"time", "m", "p", "g", "stack"},
179 // N.B. There's clearly a timestamp here, but these Events
180 // are special in that they don't appear in the regular
181 // M streams.
182 StackIDs: []int{4},
183 },
184 EvFrequency: {
185 Name: "Frequency",
186 Args: [][]byte{"freq"},
187 },
188 EvExperimentalBatch: {
189 Name: "ExperimentalBatch",
190 Args: [][]byte{"exp", "gen", "m", "time"},
191 HasData: true, // Easier to represent for raw readers.
192 },
193 EvSync: {
194 Name: "Sync",
195 },
196 EvEndOfGeneration: {
197 Name: "EndOfGeneration",
198 },
199
200 // "Timed" Events.
201 EvProcsChange: {
202 Name: "ProcsChange",
203 Args: [][]byte{"dt", "procs_value", "stack"},
204 IsTimedEvent: true,
205 StackIDs: []int{2},
206 },
207 EvProcStart: {
208 Name: "ProcStart",
209 Args: [][]byte{"dt", "p", "p_seq"},
210 IsTimedEvent: true,
211 },
212 EvProcStop: {
213 Name: "ProcStop",
214 Args: [][]byte{"dt"},
215 IsTimedEvent: true,
216 },
217 EvProcSteal: {
218 Name: "ProcSteal",
219 Args: [][]byte{"dt", "p", "p_seq", "m"},
220 IsTimedEvent: true,
221 },
222 EvProcStatus: {
223 Name: "ProcStatus",
224 Args: [][]byte{"dt", "p", "pstatus"},
225 IsTimedEvent: true,
226 },
227 EvGoCreate: {
228 Name: "GoCreate",
229 Args: [][]byte{"dt", "new_g", "new_stack", "stack"},
230 IsTimedEvent: true,
231 StackIDs: []int{3, 2},
232 },
233 EvGoCreateSyscall: {
234 Name: "GoCreateSyscall",
235 Args: [][]byte{"dt", "new_g"},
236 IsTimedEvent: true,
237 },
238 EvGoStart: {
239 Name: "GoStart",
240 Args: [][]byte{"dt", "g", "g_seq"},
241 IsTimedEvent: true,
242 },
243 EvGoDestroy: {
244 Name: "GoDestroy",
245 Args: [][]byte{"dt"},
246 IsTimedEvent: true,
247 },
248 EvGoDestroySyscall: {
249 Name: "GoDestroySyscall",
250 Args: [][]byte{"dt"},
251 IsTimedEvent: true,
252 },
253 EvGoStop: {
254 Name: "GoStop",
255 Args: [][]byte{"dt", "reason_string", "stack"},
256 IsTimedEvent: true,
257 StackIDs: []int{2},
258 StringIDs: []int{1},
259 },
260 EvGoBlock: {
261 Name: "GoBlock",
262 Args: [][]byte{"dt", "reason_string", "stack"},
263 IsTimedEvent: true,
264 StackIDs: []int{2},
265 StringIDs: []int{1},
266 },
267 EvGoUnblock: {
268 Name: "GoUnblock",
269 Args: [][]byte{"dt", "g", "g_seq", "stack"},
270 IsTimedEvent: true,
271 StackIDs: []int{3},
272 },
273 EvGoSyscallBegin: {
274 Name: "GoSyscallBegin",
275 Args: [][]byte{"dt", "p_seq", "stack"},
276 IsTimedEvent: true,
277 StackIDs: []int{2},
278 },
279 EvGoSyscallEnd: {
280 Name: "GoSyscallEnd",
281 Args: [][]byte{"dt"},
282 StartEv: EvGoSyscallBegin,
283 IsTimedEvent: true,
284 },
285 EvGoSyscallEndBlocked: {
286 Name: "GoSyscallEndBlocked",
287 Args: [][]byte{"dt"},
288 StartEv: EvGoSyscallBegin,
289 IsTimedEvent: true,
290 },
291 EvGoStatus: {
292 Name: "GoStatus",
293 Args: [][]byte{"dt", "g", "m", "gstatus"},
294 IsTimedEvent: true,
295 },
296 EvSTWBegin: {
297 Name: "STWBegin",
298 Args: [][]byte{"dt", "kind_string", "stack"},
299 IsTimedEvent: true,
300 StackIDs: []int{2},
301 StringIDs: []int{1},
302 },
303 EvSTWEnd: {
304 Name: "STWEnd",
305 Args: [][]byte{"dt"},
306 StartEv: EvSTWBegin,
307 IsTimedEvent: true,
308 },
309 EvGCActive: {
310 Name: "GCActive",
311 Args: [][]byte{"dt", "gc_seq"},
312 IsTimedEvent: true,
313 StartEv: EvGCBegin,
314 },
315 EvGCBegin: {
316 Name: "GCBegin",
317 Args: [][]byte{"dt", "gc_seq", "stack"},
318 IsTimedEvent: true,
319 StackIDs: []int{2},
320 },
321 EvGCEnd: {
322 Name: "GCEnd",
323 Args: [][]byte{"dt", "gc_seq"},
324 StartEv: EvGCBegin,
325 IsTimedEvent: true,
326 },
327 EvGCSweepActive: {
328 Name: "GCSweepActive",
329 Args: [][]byte{"dt", "p"},
330 StartEv: EvGCSweepBegin,
331 IsTimedEvent: true,
332 },
333 EvGCSweepBegin: {
334 Name: "GCSweepBegin",
335 Args: [][]byte{"dt", "stack"},
336 IsTimedEvent: true,
337 StackIDs: []int{1},
338 },
339 EvGCSweepEnd: {
340 Name: "GCSweepEnd",
341 Args: [][]byte{"dt", "swept_value", "reclaimed_value"},
342 StartEv: EvGCSweepBegin,
343 IsTimedEvent: true,
344 },
345 EvGCMarkAssistActive: {
346 Name: "GCMarkAssistActive",
347 Args: [][]byte{"dt", "g"},
348 StartEv: EvGCMarkAssistBegin,
349 IsTimedEvent: true,
350 },
351 EvGCMarkAssistBegin: {
352 Name: "GCMarkAssistBegin",
353 Args: [][]byte{"dt", "stack"},
354 IsTimedEvent: true,
355 StackIDs: []int{1},
356 },
357 EvGCMarkAssistEnd: {
358 Name: "GCMarkAssistEnd",
359 Args: [][]byte{"dt"},
360 StartEv: EvGCMarkAssistBegin,
361 IsTimedEvent: true,
362 },
363 EvHeapAlloc: {
364 Name: "HeapAlloc",
365 Args: [][]byte{"dt", "heapalloc_value"},
366 IsTimedEvent: true,
367 },
368 EvHeapGoal: {
369 Name: "HeapGoal",
370 Args: [][]byte{"dt", "heapgoal_value"},
371 IsTimedEvent: true,
372 },
373 EvGoLabel: {
374 Name: "GoLabel",
375 Args: [][]byte{"dt", "label_string"},
376 IsTimedEvent: true,
377 StringIDs: []int{1},
378 },
379 EvUserTaskBegin: {
380 Name: "UserTaskBegin",
381 Args: [][]byte{"dt", "task", "parent_task", "name_string", "stack"},
382 IsTimedEvent: true,
383 StackIDs: []int{4},
384 StringIDs: []int{3},
385 },
386 EvUserTaskEnd: {
387 Name: "UserTaskEnd",
388 Args: [][]byte{"dt", "task", "stack"},
389 IsTimedEvent: true,
390 StackIDs: []int{2},
391 },
392 EvUserRegionBegin: {
393 Name: "UserRegionBegin",
394 Args: [][]byte{"dt", "task", "name_string", "stack"},
395 IsTimedEvent: true,
396 StackIDs: []int{3},
397 StringIDs: []int{2},
398 },
399 EvUserRegionEnd: {
400 Name: "UserRegionEnd",
401 Args: [][]byte{"dt", "task", "name_string", "stack"},
402 StartEv: EvUserRegionBegin,
403 IsTimedEvent: true,
404 StackIDs: []int{3},
405 StringIDs: []int{2},
406 },
407 EvUserLog: {
408 Name: "UserLog",
409 Args: [][]byte{"dt", "task", "key_string", "value_string", "stack"},
410 IsTimedEvent: true,
411 StackIDs: []int{4},
412 StringIDs: []int{2, 3},
413 },
414 EvGoSwitch: {
415 Name: "GoSwitch",
416 Args: [][]byte{"dt", "g", "g_seq"},
417 IsTimedEvent: true,
418 },
419 EvGoSwitchDestroy: {
420 Name: "GoSwitchDestroy",
421 Args: [][]byte{"dt", "g", "g_seq"},
422 IsTimedEvent: true,
423 },
424 EvGoCreateBlocked: {
425 Name: "GoCreateBlocked",
426 Args: [][]byte{"dt", "new_g", "new_stack", "stack"},
427 IsTimedEvent: true,
428 StackIDs: []int{3, 2},
429 },
430 EvGoStatusStack: {
431 Name: "GoStatusStack",
432 Args: [][]byte{"dt", "g", "m", "gstatus", "stack"},
433 IsTimedEvent: true,
434 StackIDs: []int{4},
435 },
436 EvClockSnapshot: {
437 Name: "ClockSnapshot",
438 Args: [][]byte{"dt", "mono", "sec", "nsec"},
439 IsTimedEvent: true,
440 },
441
442 // Experimental events.
443
444 EvSpan: {
445 Name: "Span",
446 Args: [][]byte{"dt", "id", "npages_value", "kindclass"},
447 IsTimedEvent: true,
448 Experiment: AllocFree,
449 },
450 EvSpanAlloc: {
451 Name: "SpanAlloc",
452 Args: [][]byte{"dt", "id", "npages_value", "kindclass"},
453 IsTimedEvent: true,
454 Experiment: AllocFree,
455 },
456 EvSpanFree: {
457 Name: "SpanFree",
458 Args: [][]byte{"dt", "id"},
459 IsTimedEvent: true,
460 Experiment: AllocFree,
461 },
462 EvHeapObject: {
463 Name: "HeapObject",
464 Args: [][]byte{"dt", "id", "type"},
465 IsTimedEvent: true,
466 Experiment: AllocFree,
467 },
468 EvHeapObjectAlloc: {
469 Name: "HeapObjectAlloc",
470 Args: [][]byte{"dt", "id", "type"},
471 IsTimedEvent: true,
472 Experiment: AllocFree,
473 },
474 EvHeapObjectFree: {
475 Name: "HeapObjectFree",
476 Args: [][]byte{"dt", "id"},
477 IsTimedEvent: true,
478 Experiment: AllocFree,
479 },
480 EvGoroutineStack: {
481 Name: "GoroutineStack",
482 Args: [][]byte{"dt", "id", "order"},
483 IsTimedEvent: true,
484 Experiment: AllocFree,
485 },
486 EvGoroutineStackAlloc: {
487 Name: "GoroutineStackAlloc",
488 Args: [][]byte{"dt", "id", "order"},
489 IsTimedEvent: true,
490 Experiment: AllocFree,
491 },
492 EvGoroutineStackFree: {
493 Name: "GoroutineStackFree",
494 Args: [][]byte{"dt", "id"},
495 IsTimedEvent: true,
496 Experiment: AllocFree,
497 },
498 }
499
500 // GoStatus is the status of a goroutine.
501 //
502 // They correspond directly to the various goroutine states.
503 type GoStatus uint8
504
505 const (
506 GoBad GoStatus = iota
507 GoRunnable
508 GoRunning
509 GoSyscall
510 GoWaiting
511 )
512
513 func (s GoStatus) String() string {
514 switch s {
515 case GoRunnable:
516 return "Runnable"
517 case GoRunning:
518 return "Running"
519 case GoSyscall:
520 return "Syscall"
521 case GoWaiting:
522 return "Waiting"
523 }
524 return "Bad"
525 }
526
527 // ProcStatus is the status of a P.
528 //
529 // They mostly correspond to the various P states.
530 type ProcStatus uint8
531
532 const (
533 ProcBad ProcStatus = iota
534 ProcRunning
535 ProcIdle
536 ProcSyscall
537
538 // ProcSyscallAbandoned is a special case of
539 // ProcSyscall. It's used in the very specific case
540 // where the first a P is mentioned in a generation is
541 // part of a ProcSteal event. If that's the first time
542 // it's mentioned, then there's no GoSyscallBegin to
543 // connect the P stealing back to at that point. This
544 // special state indicates this to the parser, so it
545 // doesn't try to find a GoSyscallEndBlocked that
546 // corresponds with the ProcSteal.
547 ProcSyscallAbandoned
548 )
549
550 func (s ProcStatus) String() string {
551 switch s {
552 case ProcRunning:
553 return "Running"
554 case ProcIdle:
555 return "Idle"
556 case ProcSyscall:
557 return "Syscall"
558 }
559 return "Bad"
560 }
561
562 const (
563 // MaxBatchSize sets the maximum size that a batch can be.
564 //
565 // Directly controls the trace batch size in the runtime.
566 //
567 // NOTE: If this number decreases, the trace format version must change.
568 MaxBatchSize = 64 << 10
569
570 // Maximum number of PCs in a single stack trace.
571 //
572 // Since events contain only stack ID rather than whole stack trace,
573 // we can allow quite large values here.
574 //
575 // Directly controls the maximum number of frames per stack
576 // in the runtime.
577 //
578 // NOTE: If this number decreases, the trace format version must change.
579 MaxFramesPerStack = 128
580
581 // MaxEventTrailerDataSize controls the amount of trailer data that
582 // an event can have in bytes. Must be smaller than MaxBatchSize.
583 // Controls the maximum string size in the trace.
584 //
585 // Directly controls the maximum such value in the runtime.
586 //
587 // NOTE: If this number decreases, the trace format version must change.
588 MaxEventTrailerDataSize = 1 << 10
589 )
590