From: Michael Anthony Knyszek Date: Tue, 28 Jan 2025 20:59:54 +0000 (+0000) Subject: internal/trace/tracev2: add guide for trace experiments X-Git-Tag: go1.25rc1~1076 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=34e8541d24b5b6624ccc252125f832c1ea0bfa00;p=gostls13.git internal/trace/tracev2: add guide for trace experiments Change-Id: I6fb354a57f3e73bd6589570868c7d68369adcf3c Reviewed-on: https://go-review.googlesource.com/c/go/+/645136 Reviewed-by: Michael Pratt Auto-Submit: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- diff --git a/src/internal/trace/tracev2/EXPERIMENTS.md b/src/internal/trace/tracev2/EXPERIMENTS.md new file mode 100644 index 0000000000..fedf7bdbdc --- /dev/null +++ b/src/internal/trace/tracev2/EXPERIMENTS.md @@ -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.