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

View as plain text