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

View as plain text