]> Cypherpunks repositories - gostls13.git/commitdiff
internal/trace/tracev2: add guide for trace experiments
authorMichael Anthony Knyszek <mknyszek@google.com>
Tue, 28 Jan 2025 20:59:54 +0000 (20:59 +0000)
committerGopher Robot <gobot@golang.org>
Tue, 11 Feb 2025 19:23:34 +0000 (11:23 -0800)
Change-Id: I6fb354a57f3e73bd6589570868c7d68369adcf3c
Reviewed-on: https://go-review.googlesource.com/c/go/+/645136
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/internal/trace/tracev2/EXPERIMENTS.md [new file with mode: 0644]

diff --git a/src/internal/trace/tracev2/EXPERIMENTS.md b/src/internal/trace/tracev2/EXPERIMENTS.md
new file mode 100644 (file)
index 0000000..fedf7bd
--- /dev/null
@@ -0,0 +1,101 @@
+# Trace experiments
+
+Execution traces allow for trialing new events on an experimental basis via
+trace experiments.
+This document is a guide that explains how you can define your own trace
+experiments.
+
+Note that if you're just trying to do some debugging or perform some light
+instrumentation, then a trace experiment is way overkill.
+Use `runtime/trace.Log` instead.
+Even if you're just trying to create a proof-of-concept for a low-frequency
+event, `runtime/trace.Log` will probably be easier overall if you can make
+it work.
+
+Consider a trace experiment if:
+- The volume of new trace events will be relatively high, and so the events
+  would benefit from a more compact representation (creating new tables to
+  deduplicate data, taking advantage of the varint representation, etc.).
+- It's not safe to call `runtime/trace.Log` (or its runtime equivalent) in
+  the contexts you want to generate an event (for example, for events about
+  timers).
+
+## Defining a new experiment
+
+To define a new experiment, modify `internal/trace/tracev2` to define a
+new `Experiment` enum value.
+
+An experiment consists of two parts: timed events and experimental batches.
+Timed events are events like any other and follow the same format.
+They are easier to order and require less work to make use of.
+Experimental batches are essentially bags of bytes that correspond to
+an entire trace generation.
+What they contain and how they're interpreted is totally up to you, but
+they're most often useful for tables that your other events can refer into.
+For example, the AllocFree experiment uses them to store type information
+that allocation events can refer to.
+
+### Defining new events
+
+1. Define your new experiment event types (by convention, experimental events
+   types start at ID 127, so look for the `const` block defining events
+   starting there).
+2. Describe your new events in `specs`.
+   Use the documentation for `Spec` to write your new specs, and check your
+   work by running the tests in the `internal/trace/tracev2` package.
+   If you wish for your event argument to be interpreted in a particular
+   way, follow the naming convention in
+   `src/internal/trace/tracev2/spec.go`.
+   For example, if you intend to emit a string argument, make sure the
+   argument name has the suffix `string`.
+3. Add ordering and validation logic for your new events to
+   `src/internal/trace/order.go` by listing handlers for those events in
+   the `orderingDispatch` table.
+   If your events are always emitted in a regular user goroutine context,
+   then the handler should be trivial and just validate the scheduling
+   context to match userGoReqs.
+   If it's more complicated, see `(*ordering).advanceAllocFree` for a
+   slightly more complicated example that handles events from a larger
+   variety of execution environments.
+   If you need to encode a partial ordering, look toward the scheduler
+   events (names beginning with `Go`) or just ask someone for help.
+4. Add your new events to the `tracev2Type2Kind` table in
+   `src/internal/trace/event.go`.
+
+## Emitting data
+
+### Emitting your new events
+
+1. Define helper methods on `runtime.traceEventWriter` for emitting your
+   events.
+2. Instrument the runtime with calls to these helper methods.
+   Make sure to call `traceAcquire` and `traceRelease` around the operation
+   your event represents, otherwise it will not be emitted atomically with
+   that operation completing, resulting in a potentially misleading trace.
+
+### Emitting experimental batches
+
+To emit experimental batches, use the `runtime.unsafeTraceExpWriter` to
+write experimental batches associated with your experiment.
+Heed the warnings and make sure that while you write them, the trace
+generation cannot advance.
+Note that each experiment can only have one distinguishable set of
+batches.
+
+## Recovering experimental data
+
+### Recovering experimental events from the trace
+
+Experimental events will appear in the event stream as an event with the
+`EventExperimental` `Kind`.
+Use the `Experimental` method to collect the raw data inserted into the
+trace.
+It's essentially up to you to interpret the event from here.
+I recommend writing a thin wrapper API to present a cleaner interface if you
+so desire.
+
+### Recovering experimental batches
+
+Parse out all the experimental batches from `Sync` events as they come.
+These experimental batches are all for the same generation as all the
+experimental events up until the next `Sync` event.