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
5package go122
6
7import (
8	"fmt"
9	"internal/trace/event"
10)
11
12const (
13	EvNone event.Type = iota // unused
14
15	// Structural events.
16	EvEventBatch // start of per-M batch of events [generation, M ID, timestamp, batch length]
17	EvStacks     // start of a section of the stack table [...EvStack]
18	EvStack      // stack table entry [ID, ...{PC, func string ID, file string ID, line #}]
19	EvStrings    // start of a section of the string dictionary [...EvString]
20	EvString     // string dictionary entry [ID, length, string]
21	EvCPUSamples // start of a section of CPU samples [...EvCPUSample]
22	EvCPUSample  // CPU profiling sample [timestamp, M ID, P ID, goroutine ID, stack ID]
23	EvFrequency  // timestamp units per sec [freq]
24
25	// Procs.
26	EvProcsChange // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack ID]
27	EvProcStart   // start of P [timestamp, P ID, P seq]
28	EvProcStop    // stop of P [timestamp]
29	EvProcSteal   // P was stolen [timestamp, P ID, P seq, M ID]
30	EvProcStatus  // P status at the start of a generation [timestamp, P ID, status]
31
32	// Goroutines.
33	EvGoCreate            // goroutine creation [timestamp, new goroutine ID, new stack ID, stack ID]
34	EvGoCreateSyscall     // goroutine appears in syscall (cgo callback) [timestamp, new goroutine ID]
35	EvGoStart             // goroutine starts running [timestamp, goroutine ID, goroutine seq]
36	EvGoDestroy           // goroutine ends [timestamp]
37	EvGoDestroySyscall    // goroutine ends in syscall (cgo callback) [timestamp]
38	EvGoStop              // goroutine yields its time, but is runnable [timestamp, reason, stack ID]
39	EvGoBlock             // goroutine blocks [timestamp, reason, stack ID]
40	EvGoUnblock           // goroutine is unblocked [timestamp, goroutine ID, goroutine seq, stack ID]
41	EvGoSyscallBegin      // syscall enter [timestamp, P seq, stack ID]
42	EvGoSyscallEnd        // syscall exit [timestamp]
43	EvGoSyscallEndBlocked // syscall exit and it blocked at some point [timestamp]
44	EvGoStatus            // goroutine status at the start of a generation [timestamp, goroutine ID, thread ID, status]
45
46	// STW.
47	EvSTWBegin // STW start [timestamp, kind]
48	EvSTWEnd   // STW done [timestamp]
49
50	// GC events.
51	EvGCActive           // GC active [timestamp, seq]
52	EvGCBegin            // GC start [timestamp, seq, stack ID]
53	EvGCEnd              // GC done [timestamp, seq]
54	EvGCSweepActive      // GC sweep active [timestamp, P ID]
55	EvGCSweepBegin       // GC sweep start [timestamp, stack ID]
56	EvGCSweepEnd         // GC sweep done [timestamp, swept bytes, reclaimed bytes]
57	EvGCMarkAssistActive // GC mark assist active [timestamp, goroutine ID]
58	EvGCMarkAssistBegin  // GC mark assist start [timestamp, stack ID]
59	EvGCMarkAssistEnd    // GC mark assist done [timestamp]
60	EvHeapAlloc          // gcController.heapLive change [timestamp, heap alloc in bytes]
61	EvHeapGoal           // gcController.heapGoal() change [timestamp, heap goal in bytes]
62
63	// Annotations.
64	EvGoLabel         // apply string label to current running goroutine [timestamp, label string ID]
65	EvUserTaskBegin   // trace.NewTask [timestamp, internal task ID, internal parent task ID, name string ID, stack ID]
66	EvUserTaskEnd     // end of a task [timestamp, internal task ID, stack ID]
67	EvUserRegionBegin // trace.{Start,With}Region [timestamp, internal task ID, name string ID, stack ID]
68	EvUserRegionEnd   // trace.{End,With}Region [timestamp, internal task ID, name string ID, stack ID]
69	EvUserLog         // trace.Log [timestamp, internal task ID, key string ID, value string ID, stack]
70
71	// Coroutines. Added in Go 1.23.
72	EvGoSwitch        // goroutine switch (coroswitch) [timestamp, goroutine ID, goroutine seq]
73	EvGoSwitchDestroy // goroutine switch and destroy [timestamp, goroutine ID, goroutine seq]
74	EvGoCreateBlocked // goroutine creation (starts blocked) [timestamp, new goroutine ID, new stack ID, stack ID]
75
76	// GoStatus with stack. Added in Go 1.23.
77	EvGoStatusStack // goroutine status at the start of a generation, with a stack [timestamp, goroutine ID, M ID, status, stack ID]
78
79	// Batch event for an experimental batch with a custom format. Added in Go 1.23.
80	EvExperimentalBatch // start of extra data [experiment ID, generation, M ID, timestamp, batch length, batch data...]
81)
82
83// Experiments.
84const (
85	// AllocFree is the alloc-free events experiment.
86	AllocFree event.Experiment = 1 + iota
87)
88
89// Experimental events.
90const (
91	_ event.Type = 127 + iota
92
93	// Experimental events for AllocFree.
94
95	// Experimental heap span events. Added in Go 1.23.
96	EvSpan      // heap span exists [timestamp, id, npages, type/class]
97	EvSpanAlloc // heap span alloc [timestamp, id, npages, type/class]
98	EvSpanFree  // heap span free [timestamp, id]
99
100	// Experimental heap object events. Added in Go 1.23.
101	EvHeapObject      // heap object exists [timestamp, id, type]
102	EvHeapObjectAlloc // heap object alloc [timestamp, id, type]
103	EvHeapObjectFree  // heap object free [timestamp, id]
104
105	// Experimental goroutine stack events. Added in Go 1.23.
106	EvGoroutineStack      // stack exists [timestamp, id, order]
107	EvGoroutineStackAlloc // stack alloc [timestamp, id, order]
108	EvGoroutineStackFree  // stack free [timestamp, id]
109)
110
111// EventString returns the name of a Go 1.22 event.
112func EventString(typ event.Type) string {
113	if int(typ) < len(specs) {
114		return specs[typ].Name
115	}
116	return fmt.Sprintf("Invalid(%d)", typ)
117}
118
119func Specs() []event.Spec {
120	return specs[:]
121}
122
123var specs = [...]event.Spec{
124	// "Structural" Events.
125	EvEventBatch: event.Spec{
126		Name: "EventBatch",
127		Args: []string{"gen", "m", "time", "size"},
128	},
129	EvStacks: event.Spec{
130		Name: "Stacks",
131	},
132	EvStack: event.Spec{
133		Name:    "Stack",
134		Args:    []string{"id", "nframes"},
135		IsStack: true,
136	},
137	EvStrings: event.Spec{
138		Name: "Strings",
139	},
140	EvString: event.Spec{
141		Name:    "String",
142		Args:    []string{"id"},
143		HasData: true,
144	},
145	EvCPUSamples: event.Spec{
146		Name: "CPUSamples",
147	},
148	EvCPUSample: event.Spec{
149		Name: "CPUSample",
150		Args: []string{"time", "m", "p", "g", "stack"},
151		// N.B. There's clearly a timestamp here, but these Events
152		// are special in that they don't appear in the regular
153		// M streams.
154	},
155	EvFrequency: event.Spec{
156		Name: "Frequency",
157		Args: []string{"freq"},
158	},
159	EvExperimentalBatch: event.Spec{
160		Name:    "ExperimentalBatch",
161		Args:    []string{"exp", "gen", "m", "time"},
162		HasData: true, // Easier to represent for raw readers.
163	},
164
165	// "Timed" Events.
166	EvProcsChange: event.Spec{
167		Name:         "ProcsChange",
168		Args:         []string{"dt", "procs_value", "stack"},
169		IsTimedEvent: true,
170		StackIDs:     []int{2},
171	},
172	EvProcStart: event.Spec{
173		Name:         "ProcStart",
174		Args:         []string{"dt", "p", "p_seq"},
175		IsTimedEvent: true,
176	},
177	EvProcStop: event.Spec{
178		Name:         "ProcStop",
179		Args:         []string{"dt"},
180		IsTimedEvent: true,
181	},
182	EvProcSteal: event.Spec{
183		Name:         "ProcSteal",
184		Args:         []string{"dt", "p", "p_seq", "m"},
185		IsTimedEvent: true,
186	},
187	EvProcStatus: event.Spec{
188		Name:         "ProcStatus",
189		Args:         []string{"dt", "p", "pstatus"},
190		IsTimedEvent: true,
191	},
192	EvGoCreate: event.Spec{
193		Name:         "GoCreate",
194		Args:         []string{"dt", "new_g", "new_stack", "stack"},
195		IsTimedEvent: true,
196		StackIDs:     []int{3, 2},
197	},
198	EvGoCreateSyscall: event.Spec{
199		Name:         "GoCreateSyscall",
200		Args:         []string{"dt", "new_g"},
201		IsTimedEvent: true,
202	},
203	EvGoStart: event.Spec{
204		Name:         "GoStart",
205		Args:         []string{"dt", "g", "g_seq"},
206		IsTimedEvent: true,
207	},
208	EvGoDestroy: event.Spec{
209		Name:         "GoDestroy",
210		Args:         []string{"dt"},
211		IsTimedEvent: true,
212	},
213	EvGoDestroySyscall: event.Spec{
214		Name:         "GoDestroySyscall",
215		Args:         []string{"dt"},
216		IsTimedEvent: true,
217	},
218	EvGoStop: event.Spec{
219		Name:         "GoStop",
220		Args:         []string{"dt", "reason_string", "stack"},
221		IsTimedEvent: true,
222		StackIDs:     []int{2},
223		StringIDs:    []int{1},
224	},
225	EvGoBlock: event.Spec{
226		Name:         "GoBlock",
227		Args:         []string{"dt", "reason_string", "stack"},
228		IsTimedEvent: true,
229		StackIDs:     []int{2},
230		StringIDs:    []int{1},
231	},
232	EvGoUnblock: event.Spec{
233		Name:         "GoUnblock",
234		Args:         []string{"dt", "g", "g_seq", "stack"},
235		IsTimedEvent: true,
236		StackIDs:     []int{3},
237	},
238	EvGoSyscallBegin: event.Spec{
239		Name:         "GoSyscallBegin",
240		Args:         []string{"dt", "p_seq", "stack"},
241		IsTimedEvent: true,
242		StackIDs:     []int{2},
243	},
244	EvGoSyscallEnd: event.Spec{
245		Name:         "GoSyscallEnd",
246		Args:         []string{"dt"},
247		StartEv:      EvGoSyscallBegin,
248		IsTimedEvent: true,
249	},
250	EvGoSyscallEndBlocked: event.Spec{
251		Name:         "GoSyscallEndBlocked",
252		Args:         []string{"dt"},
253		StartEv:      EvGoSyscallBegin,
254		IsTimedEvent: true,
255	},
256	EvGoStatus: event.Spec{
257		Name:         "GoStatus",
258		Args:         []string{"dt", "g", "m", "gstatus"},
259		IsTimedEvent: true,
260	},
261	EvSTWBegin: event.Spec{
262		Name:         "STWBegin",
263		Args:         []string{"dt", "kind_string", "stack"},
264		IsTimedEvent: true,
265		StackIDs:     []int{2},
266		StringIDs:    []int{1},
267	},
268	EvSTWEnd: event.Spec{
269		Name:         "STWEnd",
270		Args:         []string{"dt"},
271		StartEv:      EvSTWBegin,
272		IsTimedEvent: true,
273	},
274	EvGCActive: event.Spec{
275		Name:         "GCActive",
276		Args:         []string{"dt", "gc_seq"},
277		IsTimedEvent: true,
278		StartEv:      EvGCBegin,
279	},
280	EvGCBegin: event.Spec{
281		Name:         "GCBegin",
282		Args:         []string{"dt", "gc_seq", "stack"},
283		IsTimedEvent: true,
284		StackIDs:     []int{2},
285	},
286	EvGCEnd: event.Spec{
287		Name:         "GCEnd",
288		Args:         []string{"dt", "gc_seq"},
289		StartEv:      EvGCBegin,
290		IsTimedEvent: true,
291	},
292	EvGCSweepActive: event.Spec{
293		Name:         "GCSweepActive",
294		Args:         []string{"dt", "p"},
295		StartEv:      EvGCSweepBegin,
296		IsTimedEvent: true,
297	},
298	EvGCSweepBegin: event.Spec{
299		Name:         "GCSweepBegin",
300		Args:         []string{"dt", "stack"},
301		IsTimedEvent: true,
302		StackIDs:     []int{1},
303	},
304	EvGCSweepEnd: event.Spec{
305		Name:         "GCSweepEnd",
306		Args:         []string{"dt", "swept_value", "reclaimed_value"},
307		StartEv:      EvGCSweepBegin,
308		IsTimedEvent: true,
309	},
310	EvGCMarkAssistActive: event.Spec{
311		Name:         "GCMarkAssistActive",
312		Args:         []string{"dt", "g"},
313		StartEv:      EvGCMarkAssistBegin,
314		IsTimedEvent: true,
315	},
316	EvGCMarkAssistBegin: event.Spec{
317		Name:         "GCMarkAssistBegin",
318		Args:         []string{"dt", "stack"},
319		IsTimedEvent: true,
320		StackIDs:     []int{1},
321	},
322	EvGCMarkAssistEnd: event.Spec{
323		Name:         "GCMarkAssistEnd",
324		Args:         []string{"dt"},
325		StartEv:      EvGCMarkAssistBegin,
326		IsTimedEvent: true,
327	},
328	EvHeapAlloc: event.Spec{
329		Name:         "HeapAlloc",
330		Args:         []string{"dt", "heapalloc_value"},
331		IsTimedEvent: true,
332	},
333	EvHeapGoal: event.Spec{
334		Name:         "HeapGoal",
335		Args:         []string{"dt", "heapgoal_value"},
336		IsTimedEvent: true,
337	},
338	EvGoLabel: event.Spec{
339		Name:         "GoLabel",
340		Args:         []string{"dt", "label_string"},
341		IsTimedEvent: true,
342		StringIDs:    []int{1},
343	},
344	EvUserTaskBegin: event.Spec{
345		Name:         "UserTaskBegin",
346		Args:         []string{"dt", "task", "parent_task", "name_string", "stack"},
347		IsTimedEvent: true,
348		StackIDs:     []int{4},
349		StringIDs:    []int{3},
350	},
351	EvUserTaskEnd: event.Spec{
352		Name:         "UserTaskEnd",
353		Args:         []string{"dt", "task", "stack"},
354		IsTimedEvent: true,
355		StackIDs:     []int{2},
356	},
357	EvUserRegionBegin: event.Spec{
358		Name:         "UserRegionBegin",
359		Args:         []string{"dt", "task", "name_string", "stack"},
360		IsTimedEvent: true,
361		StackIDs:     []int{3},
362		StringIDs:    []int{2},
363	},
364	EvUserRegionEnd: event.Spec{
365		Name:         "UserRegionEnd",
366		Args:         []string{"dt", "task", "name_string", "stack"},
367		StartEv:      EvUserRegionBegin,
368		IsTimedEvent: true,
369		StackIDs:     []int{3},
370		StringIDs:    []int{2},
371	},
372	EvUserLog: event.Spec{
373		Name:         "UserLog",
374		Args:         []string{"dt", "task", "key_string", "value_string", "stack"},
375		IsTimedEvent: true,
376		StackIDs:     []int{4},
377		StringIDs:    []int{2, 3},
378	},
379	EvGoSwitch: event.Spec{
380		Name:         "GoSwitch",
381		Args:         []string{"dt", "g", "g_seq"},
382		IsTimedEvent: true,
383	},
384	EvGoSwitchDestroy: event.Spec{
385		Name:         "GoSwitchDestroy",
386		Args:         []string{"dt", "g", "g_seq"},
387		IsTimedEvent: true,
388	},
389	EvGoCreateBlocked: event.Spec{
390		Name:         "GoCreateBlocked",
391		Args:         []string{"dt", "new_g", "new_stack", "stack"},
392		IsTimedEvent: true,
393		StackIDs:     []int{3, 2},
394	},
395	EvGoStatusStack: event.Spec{
396		Name:         "GoStatusStack",
397		Args:         []string{"dt", "g", "m", "gstatus", "stack"},
398		IsTimedEvent: true,
399		StackIDs:     []int{4},
400	},
401
402	// Experimental events.
403
404	EvSpan: event.Spec{
405		Name:         "Span",
406		Args:         []string{"dt", "id", "npages_value", "kindclass"},
407		IsTimedEvent: true,
408		Experiment:   AllocFree,
409	},
410	EvSpanAlloc: event.Spec{
411		Name:         "SpanAlloc",
412		Args:         []string{"dt", "id", "npages_value", "kindclass"},
413		IsTimedEvent: true,
414		Experiment:   AllocFree,
415	},
416	EvSpanFree: event.Spec{
417		Name:         "SpanFree",
418		Args:         []string{"dt", "id"},
419		IsTimedEvent: true,
420		Experiment:   AllocFree,
421	},
422	EvHeapObject: event.Spec{
423		Name:         "HeapObject",
424		Args:         []string{"dt", "id", "type"},
425		IsTimedEvent: true,
426		Experiment:   AllocFree,
427	},
428	EvHeapObjectAlloc: event.Spec{
429		Name:         "HeapObjectAlloc",
430		Args:         []string{"dt", "id", "type"},
431		IsTimedEvent: true,
432		Experiment:   AllocFree,
433	},
434	EvHeapObjectFree: event.Spec{
435		Name:         "HeapObjectFree",
436		Args:         []string{"dt", "id"},
437		IsTimedEvent: true,
438		Experiment:   AllocFree,
439	},
440	EvGoroutineStack: event.Spec{
441		Name:         "GoroutineStack",
442		Args:         []string{"dt", "id", "order"},
443		IsTimedEvent: true,
444		Experiment:   AllocFree,
445	},
446	EvGoroutineStackAlloc: event.Spec{
447		Name:         "GoroutineStackAlloc",
448		Args:         []string{"dt", "id", "order"},
449		IsTimedEvent: true,
450		Experiment:   AllocFree,
451	},
452	EvGoroutineStackFree: event.Spec{
453		Name:         "GoroutineStackFree",
454		Args:         []string{"dt", "id"},
455		IsTimedEvent: true,
456		Experiment:   AllocFree,
457	},
458}
459
460type GoStatus uint8
461
462const (
463	GoBad GoStatus = iota
464	GoRunnable
465	GoRunning
466	GoSyscall
467	GoWaiting
468)
469
470func (s GoStatus) String() string {
471	switch s {
472	case GoRunnable:
473		return "Runnable"
474	case GoRunning:
475		return "Running"
476	case GoSyscall:
477		return "Syscall"
478	case GoWaiting:
479		return "Waiting"
480	}
481	return "Bad"
482}
483
484type ProcStatus uint8
485
486const (
487	ProcBad ProcStatus = iota
488	ProcRunning
489	ProcIdle
490	ProcSyscall
491	ProcSyscallAbandoned
492)
493
494func (s ProcStatus) String() string {
495	switch s {
496	case ProcRunning:
497		return "Running"
498	case ProcIdle:
499		return "Idle"
500	case ProcSyscall:
501		return "Syscall"
502	}
503	return "Bad"
504}
505
506const (
507	// Various format-specific constants.
508	MaxBatchSize      = 64 << 10
509	MaxFramesPerStack = 128
510	MaxStringSize     = 1 << 10
511)
512