This avoids the asynchrony related to the pipe+buffer+goroutine. Using
this approach, we can guarantee that once the `Write` call completes,
the data is stored in flightrecorder buffers. This is related to
https://go.dev/cl/562616.
There is a behavioral change: previously, in case of error the recorder
goroutine would just stop, which would essentially block the tracing
infra by not accepting the `Write`. Now, we actively stop tracing on any
error.
I did not do real performance tests, but it can't be very different:
Before:
running go [test . -count 10]
ok golang.org/x/exp/trace 60.423s
After:
running go [test . -count 10]
ok golang.org/x/exp/trace 60.394s
Change-Id: Ie900fec2b45f1c227c82e68f4f7af1902de3582b
Reviewed-on: https://go-review.googlesource.com/c/exp/+/566255
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This change adds an experimental flight recorder API that lives outside
the Go runtime. It implements the same API as the proposed API, but
has a few caveats because it exists outside the runtime.
Firstly, because the conceptual circular buffer lives outside the
runtime, this flight recorder has slightly more overhead than a
runtime-internal implementation would. Specifically, all the trace data
needs to be copied out of the runtime and gently processed, and this
process needs to happen continuously. Peak memory use is also going to
be higher because of this copying.
Secondly, the flight recorder needs to flush the runtime's buffers twice
in a row in order to obtain the snapshot it wants. This is because the
signal in the trace that a generation is done is either that the trace
stream ends or a batch with a new generation value appears. Flushing
twice in a row ensures that the generation we actually wanted done is
complete, at the cost of an additional flush. The overhead of this
should be minimal in practice, but it does mean that the actual flush
operation will have a substantially longer latency than with a
runtime-internal implementation. This is OK because that latency doesn't
actually affect any properties of the resulting snapshot; it's purely
latency to the caller. This problem could have been avoided with an
explicit in-band signal that a generation has been flushed, which we may
want to consider adding in the future.
For #63185.
Change-Id: I7a94e2cddcfbf19a4140b398c188c3d59f8b9c9e
Reviewed-on: https://go-review.googlesource.com/c/exp/+/550257
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>