Source file src/runtime/traceevent.go

     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  // Trace event writing API for trace2runtime.go.
     6  
     7  package runtime
     8  
     9  import (
    10  	"internal/abi"
    11  	"internal/runtime/sys"
    12  )
    13  
    14  // Event types in the trace, args are given in square brackets.
    15  //
    16  // Naming scheme:
    17  //   - Time range event pairs have suffixes "Begin" and "End".
    18  //   - "Start", "Stop", "Create", "Destroy", "Block", "Unblock"
    19  //     are suffixes reserved for scheduling resources.
    20  //
    21  // NOTE: If you add an event type, make sure you also update all
    22  // tables in this file!
    23  type traceEv uint8
    24  
    25  const (
    26  	traceEvNone traceEv = iota // unused
    27  
    28  	// Structural events.
    29  	traceEvEventBatch // start of per-M batch of events [generation, M ID, timestamp, batch length]
    30  	traceEvStacks     // start of a section of the stack table [...traceEvStack]
    31  	traceEvStack      // stack table entry [ID, ...{PC, func string ID, file string ID, line #}]
    32  	traceEvStrings    // start of a section of the string dictionary [...traceEvString]
    33  	traceEvString     // string dictionary entry [ID, length, string]
    34  	traceEvCPUSamples // start of a section of CPU samples [...traceEvCPUSample]
    35  	traceEvCPUSample  // CPU profiling sample [timestamp, M ID, P ID, goroutine ID, stack ID]
    36  	traceEvFrequency  // timestamp units per sec [freq]
    37  
    38  	// Procs.
    39  	traceEvProcsChange // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack ID]
    40  	traceEvProcStart   // start of P [timestamp, P ID, P seq]
    41  	traceEvProcStop    // stop of P [timestamp]
    42  	traceEvProcSteal   // P was stolen [timestamp, P ID, P seq, M ID]
    43  	traceEvProcStatus  // P status at the start of a generation [timestamp, P ID, status]
    44  
    45  	// Goroutines.
    46  	traceEvGoCreate            // goroutine creation [timestamp, new goroutine ID, new stack ID, stack ID]
    47  	traceEvGoCreateSyscall     // goroutine appears in syscall (cgo callback) [timestamp, new goroutine ID]
    48  	traceEvGoStart             // goroutine starts running [timestamp, goroutine ID, goroutine seq]
    49  	traceEvGoDestroy           // goroutine ends [timestamp]
    50  	traceEvGoDestroySyscall    // goroutine ends in syscall (cgo callback) [timestamp]
    51  	traceEvGoStop              // goroutine yields its time, but is runnable [timestamp, reason, stack ID]
    52  	traceEvGoBlock             // goroutine blocks [timestamp, reason, stack ID]
    53  	traceEvGoUnblock           // goroutine is unblocked [timestamp, goroutine ID, goroutine seq, stack ID]
    54  	traceEvGoSyscallBegin      // syscall enter [timestamp, P seq, stack ID]
    55  	traceEvGoSyscallEnd        // syscall exit [timestamp]
    56  	traceEvGoSyscallEndBlocked // syscall exit and it blocked at some point [timestamp]
    57  	traceEvGoStatus            // goroutine status at the start of a generation [timestamp, goroutine ID, M ID, status]
    58  
    59  	// STW.
    60  	traceEvSTWBegin // STW start [timestamp, kind]
    61  	traceEvSTWEnd   // STW done [timestamp]
    62  
    63  	// GC events.
    64  	traceEvGCActive           // GC active [timestamp, seq]
    65  	traceEvGCBegin            // GC start [timestamp, seq, stack ID]
    66  	traceEvGCEnd              // GC done [timestamp, seq]
    67  	traceEvGCSweepActive      // GC sweep active [timestamp, P ID]
    68  	traceEvGCSweepBegin       // GC sweep start [timestamp, stack ID]
    69  	traceEvGCSweepEnd         // GC sweep done [timestamp, swept bytes, reclaimed bytes]
    70  	traceEvGCMarkAssistActive // GC mark assist active [timestamp, goroutine ID]
    71  	traceEvGCMarkAssistBegin  // GC mark assist start [timestamp, stack ID]
    72  	traceEvGCMarkAssistEnd    // GC mark assist done [timestamp]
    73  	traceEvHeapAlloc          // gcController.heapLive change [timestamp, heap alloc in bytes]
    74  	traceEvHeapGoal           // gcController.heapGoal() change [timestamp, heap goal in bytes]
    75  
    76  	// Annotations.
    77  	traceEvGoLabel         // apply string label to current running goroutine [timestamp, label string ID]
    78  	traceEvUserTaskBegin   // trace.NewTask [timestamp, internal task ID, internal parent task ID, name string ID, stack ID]
    79  	traceEvUserTaskEnd     // end of a task [timestamp, internal task ID, stack ID]
    80  	traceEvUserRegionBegin // trace.{Start,With}Region [timestamp, internal task ID, name string ID, stack ID]
    81  	traceEvUserRegionEnd   // trace.{End,With}Region [timestamp, internal task ID, name string ID, stack ID]
    82  	traceEvUserLog         // trace.Log [timestamp, internal task ID, key string ID, stack, value string ID]
    83  
    84  	// Coroutines.
    85  	traceEvGoSwitch        // goroutine switch (coroswitch) [timestamp, goroutine ID, goroutine seq]
    86  	traceEvGoSwitchDestroy // goroutine switch and destroy [timestamp, goroutine ID, goroutine seq]
    87  	traceEvGoCreateBlocked // goroutine creation (starts blocked) [timestamp, new goroutine ID, new stack ID, stack ID]
    88  
    89  	// GoStatus with stack.
    90  	traceEvGoStatusStack // goroutine status at the start of a generation, with a stack [timestamp, goroutine ID, M ID, status, stack ID]
    91  
    92  	// Batch event for an experimental batch with a custom format.
    93  	traceEvExperimentalBatch // start of extra data [experiment ID, generation, M ID, timestamp, batch length, batch data...]
    94  )
    95  
    96  // traceArg is a simple wrapper type to help ensure that arguments passed
    97  // to traces are well-formed.
    98  type traceArg uint64
    99  
   100  // traceEventWriter is the high-level API for writing trace events.
   101  //
   102  // See the comment on traceWriter about style for more details as to why
   103  // this type and its methods are structured the way they are.
   104  type traceEventWriter struct {
   105  	tl traceLocker
   106  }
   107  
   108  // eventWriter creates a new traceEventWriter. It is the main entrypoint for writing trace events.
   109  //
   110  // Before creating the event writer, this method will emit a status for the current goroutine
   111  // or proc if it exists, and if it hasn't had its status emitted yet. goStatus and procStatus indicate
   112  // what the status of goroutine or P should be immediately *before* the events that are about to
   113  // be written using the eventWriter (if they exist). No status will be written if there's no active
   114  // goroutine or P.
   115  //
   116  // Callers can elect to pass a constant value here if the status is clear (e.g. a goroutine must have
   117  // been Runnable before a GoStart). Otherwise, callers can query the status of either the goroutine
   118  // or P and pass the appropriate status.
   119  //
   120  // In this case, the default status should be traceGoBad or traceProcBad to help identify bugs sooner.
   121  func (tl traceLocker) eventWriter(goStatus traceGoStatus, procStatus traceProcStatus) traceEventWriter {
   122  	if pp := tl.mp.p.ptr(); pp != nil && !pp.trace.statusWasTraced(tl.gen) && pp.trace.acquireStatus(tl.gen) {
   123  		tl.writer().writeProcStatus(uint64(pp.id), procStatus, pp.trace.inSweep).end()
   124  	}
   125  	if gp := tl.mp.curg; gp != nil && !gp.trace.statusWasTraced(tl.gen) && gp.trace.acquireStatus(tl.gen) {
   126  		tl.writer().writeGoStatus(uint64(gp.goid), int64(tl.mp.procid), goStatus, gp.inMarkAssist, 0 /* no stack */).end()
   127  	}
   128  	return traceEventWriter{tl}
   129  }
   130  
   131  // event writes out a trace event.
   132  func (e traceEventWriter) event(ev traceEv, args ...traceArg) {
   133  	e.tl.writer().event(ev, args...).end()
   134  }
   135  
   136  // stack takes a stack trace skipping the provided number of frames.
   137  // It then returns a traceArg representing that stack which may be
   138  // passed to write.
   139  func (tl traceLocker) stack(skip int) traceArg {
   140  	return traceArg(traceStack(skip, nil, tl.gen))
   141  }
   142  
   143  // startPC takes a start PC for a goroutine and produces a unique
   144  // stack ID for it.
   145  //
   146  // It then returns a traceArg representing that stack which may be
   147  // passed to write.
   148  func (tl traceLocker) startPC(pc uintptr) traceArg {
   149  	// +PCQuantum because makeTraceFrame expects return PCs and subtracts PCQuantum.
   150  	return traceArg(trace.stackTab[tl.gen%2].put([]uintptr{
   151  		logicalStackSentinel,
   152  		startPCForTrace(pc) + sys.PCQuantum,
   153  	}))
   154  }
   155  
   156  // string returns a traceArg representing s which may be passed to write.
   157  // The string is assumed to be relatively short and popular, so it may be
   158  // stored for a while in the string dictionary.
   159  func (tl traceLocker) string(s string) traceArg {
   160  	return traceArg(trace.stringTab[tl.gen%2].put(tl.gen, s))
   161  }
   162  
   163  // uniqueString returns a traceArg representing s which may be passed to write.
   164  // The string is assumed to be unique or long, so it will be written out to
   165  // the trace eagerly.
   166  func (tl traceLocker) uniqueString(s string) traceArg {
   167  	return traceArg(trace.stringTab[tl.gen%2].emit(tl.gen, s))
   168  }
   169  
   170  // rtype returns a traceArg representing typ which may be passed to write.
   171  func (tl traceLocker) rtype(typ *abi.Type) traceArg {
   172  	return traceArg(trace.typeTab[tl.gen%2].put(typ))
   173  }
   174  

View as plain text