Skip to content

Commit 8c6fec6

Browse files
mknyszekgopherbot
authored andcommitted
runtime: update HACKING.md with execution traces and debuglog
Change-Id: Iedd3c6f292ad76f57c6c04beafd655e2e4d83043 Reviewed-on: https://go-review.googlesource.com/c/go/+/646017 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Pratt <[email protected]> Auto-Submit: Michael Knyszek <[email protected]>
1 parent 34e8541 commit 8c6fec6

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

src/runtime/HACKING.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,69 @@ transitive calls) to prevent stack growth.
330330
The conversion from pointer to uintptr must appear in the argument list of any
331331
call to this function. This directive is used for some low-level system call
332332
implementations.
333+
334+
Execution tracer
335+
================
336+
337+
The execution tracer is a way for users to see what their goroutines are doing,
338+
but they're also useful for runtime hacking.
339+
340+
Using execution traces to debug runtime problems
341+
------------------------------------------------
342+
343+
Execution traces contain a wealth of information about what the runtime is
344+
doing. They contain all goroutine scheduling actions, data about time spent in
345+
the scheduler (P running without a G), data about time spent in the garbage
346+
collector, and more. Use `go tool trace` or [gotraceui](https://gotraceui.dev)
347+
to inspect traces.
348+
349+
Traces are especially useful for debugging latency issues, and especially if you
350+
can catch the problem in the act. Consider using the flight recorder to help
351+
with this.
352+
353+
Turn on CPU profiling when you take a trace. This will put the CPU profiling
354+
samples as timestamped events into the trace, allowing you to see execution with
355+
greater detail. If you see CPU profiling sample events appear at a rate that does
356+
not match the sample rate, consider that the OS or platform might be taking away
357+
CPU time from the process, and that you might not be debugging a Go issue.
358+
359+
If you're really stuck on a problem, adding new instrumentation with the tracer
360+
might help, especially if it's helpful to see events in relation to other
361+
scheduling events. See the next section on modifying the execution tracer.
362+
However, consider using `debuglog` for additional instrumentation first, as that
363+
is far easier to get started with.
364+
365+
Notes on modifying the execution tracer
366+
---------------------------------------
367+
368+
The execution tracer lives in the files whose names start with "trace."
369+
The parser for the execution trace format lives in the `internal/trace` package.
370+
371+
If you plan on adding new trace events, consider starting with a [trace
372+
experiment](../internal/trace/tracev2/EXPERIMENTS.md).
373+
374+
If you plan to add new trace instrumentation to the runtime, wrap whatever operation
375+
you're tracing in `traceAcquire` and `traceRelease` fully. These functions mark a
376+
critical section that appears atomic to the execution tracer (but nothing else).
377+
378+
debuglog
379+
========
380+
381+
`debuglog` is a powerful runtime-only debugging tool. Think of it as an
382+
ultra-low-overhead `println` that works just about anywhere in the runtime.
383+
These properties are invaluable when debugging subtle problems in tricky parts
384+
of the codebase. `println` can often perturb code enough to stop data races from
385+
happening, while `debuglog` perturbs execution far less.
386+
387+
`debuglog` accumulates log messages in a ring buffer on each M, and dumps out
388+
the contents, ordering it by timestamp, on certain kinds of crashes. Some messages
389+
might be lost if the ring buffer gets full, in which case consider increasing the
390+
size, or just work with a partial log.
391+
392+
1. Add `debuglog` instrumentation to the runtime. Don't forget to call `end`!
393+
Example: `dlog().s("hello world").u32(5).end()`
394+
2. By default, `debuglog` only dumps its contents in certain kinds of crashes.
395+
Consider adding more calls to `printDebugLog` if you're not getting any output.
396+
3. Build the program you wish to debug with the `debuglog` build tag.
397+
398+
`debuglog` is lower level than execution traces, and much easier to set up.

0 commit comments

Comments
 (0)