78 Commits
Author SHA1 Message Date
Jing Chen a093ad0450 Simplify and format gVisor codebase.
The changes are just output of `gofmt -s -w .`.
2024-10-13 00:50:32 -07:00
Etienne PerotandgVisor bot 2511e2e937 Actually support arbitrary number of fields in uint64 metrics.
PiperOrigin-RevId: 668653086
2024-08-28 16:35:28 -07:00
Etienne PerotandgVisor bot f02eece40d Profiling metrics: Support metrics with fields.
No visualization support yet.

PiperOrigin-RevId: 666928297
2024-08-23 14:45:42 -07:00
Etienne PerotandgVisor bot 5d5ad19204 Fine-tune and explain profiling metrics collection cycle parameters.
On my machine, for a 100 microsecond profiling rate, this brings the
measurement timing error from ~400% to 0.3%.

PiperOrigin-RevId: 648589363
2024-07-01 22:15:32 -07:00
Etienne PerotandgVisor bot 00fbbcb511 Profiling metrics: Log and display statistics about the measurement errors.
This adds log lines (in the Sentry logs) and warnings (in the metricsviz HTML
page) in case the profiling process encountered significant measurement
errors.

PiperOrigin-RevId: 648569118
2024-07-01 20:25:16 -07:00
Etienne PerotandgVisor bot 1456ad035c Profiling metrics: Record statistics about measurement errors.
This is logged in the profiling metrics log and shown in the metrics
visualization page, with warnings and suggested fixes depending on the type
of measurement error that occurs.

The errors measured are:

- Missed snapshots, as detected by the number of expected snapshots given
  the time the collection goroutine ran vs its expected profiling rate.
- Buffer overruns, as detected by the presence of backoff sleeps.
- Collection timing error, as detected by the amount of time elapsed
  between the first and the last metric in a single collection cycle
  as a fraction of the profiling rate.
- Sleep timing error, as detected by the amount of time between the
  expected collection cycle start time and the actual collection cycle
  start time, as a fraction of the profiling rate.

PiperOrigin-RevId: 648543674
2024-07-01 18:10:20 -07:00
Etienne PerotandgVisor bot b820ce292e Profiling metrics: Do not use time.Now and rely only on runtime.nanotime.
This simplifies clock handling. `runtime.nanotime` uses `CLOCK_MONOTONIC`
which works just fine.

PiperOrigin-RevId: 648528699
2024-07-01 17:08:32 -07:00
Etienne PerotandgVisor bot d436e16e6b When starting metric profiling, truncate existing profile log if applicable.
Prior to this change, if `runsc` was configured to use a specific
`--profiling-metrics-log` path, then the second run of this runtime would
overwrite existing metric data in-place, which produces a corrupt file.

This change truncates the existing log, so that the resulting log actually
correspond to what just ran.

This only happens when the `os.File` supports `truncate(2)`, which stdout
does not, so the error is ignored if there is one. It's a best-effort thing.

PiperOrigin-RevId: 648493697
2024-07-01 14:55:08 -07:00
Etienne PerotandgVisor bot b9fac79737 Fix comment for CheapNowNano.
PiperOrigin-RevId: 647498384
2024-06-27 17:38:10 -07:00
Etienne PerotandgVisor bot abde965590 Metrics: Refactor uint64 metric constructor, allow non-cumulative gauges.
This turns the uint64 metric constructor arguments into a struct, making it
more explicit as to what each part means. It also allows the creation of
non-cumulative uint64 (gauge) metrics, and adds methods to decrement or set
them.

PiperOrigin-RevId: 647134245
2024-06-26 17:41:24 -07:00
Etienne PerotandgVisor bot 341dac1be9 Profiling metrics: Make profiling metric collection more reliable.
This includes multiple improvements which, when combined, get me a clean
run on a long-running benchmark like `bazel_test` with a 100μs sample rate.

This includes:

- Not using `time.Sleep` for short durations (this made the most impact),
  instead it either spins or yields.
- Adaptive initially-faster backoff time that increases exponentially if
  it finds that it's not not sleeping long enough, rather than 100x
  profiling rate backoff right off the bat.
- Larger buffers.
- More precise computation for duration by using a mix of `nanotime` and
  actual `time.Now` readjusted once every N collections.
- Using an atomic boolean for checking if metric collection should be stopped
  (should be cheaper than checking if a channel has data).
- Putting the ringbuffer item slice being processed on the collector/writer
  stacks rather than dereferencing it for each cell.

PiperOrigin-RevId: 634123127
2024-05-15 16:59:14 -07:00
Etienne PerotandgVisor bot 2c842da781 Profiling metrics: Add per-line checksum to output.
This allows detecting data corruption more finely.

A future change will make these errors skipped over, allowing data to
still be visualized even if partially corrupt.

PiperOrigin-RevId: 634038986
2024-05-15 12:30:44 -07:00
Etienne PerotandgVisor bot 1d800dc14b Set default test container log config to allow higher logging volume.
This is part of a series of changes to add metric charts in performance
benchmarks.

This is intended to increase the reliability of logs-based profiling metrics
by ensuring that Docker keeps enough of them around during long tests, or
tests where there are a lot of metrics being profiled, or tests with a very
fast profiling rate, or all of the above.

This also calls `sync` on the underlying logging file descriptor if possible.

Give a more helpful error messages if a log buffer overrun does occur.

PiperOrigin-RevId: 633389921
2024-05-13 18:07:57 -07:00
Jing ChenandgVisor bot cf5c4c9cbf Replace reflect.DeepEqual with [slices/maps].Equal.
They are faster on slice/map comparisons.

PiperOrigin-RevId: 633080355
2024-05-12 21:20:18 -07:00
Etienne PerotandgVisor bot 998c9dd1ca Profiling metrics: Write metric metadata as part of output.
This is part of a series of changes to add metric charts in performance
benchmarks.

This helps make the logs self-contained by ensuring they carry the metric
metadata needed to chart them. Specifically, this helps the charting tool
know the meaning and type of metrics. The descriptions show up in the charts,
and the cumulative-ness determines whether the chart should show the data on
an absolute basis, or compute and show a delta-over-time.

PiperOrigin-RevId: 631322173
2024-05-07 00:43:13 -07:00
Etienne PerotandgVisor bot 1f65d99912 Profiling metrics: Support unprefixed data logging.
This is part of a series of changes to add metric charts in performance
benchmarks.

In contexts where profiling metrics are not being intermixed with other
logs, we do not have to prefix the data with a common prefix, nor do we
need the checksum. To keep profiling metric overhead to a minimum in these
cases, this distinguishes two types of writers:

- Normal buffered writers, which do nothing other than buffer writes to
  the underlying writer.
- Line-buffered "lossy" writers, which do the prefixing and checksumming
  that the code was previously doing.

Both can reuse the same underlying write loop (thanks Go generics!).

PiperOrigin-RevId: 631271157
2024-05-06 20:21:51 -07:00
Etienne PerotandgVisor bot 8a1514cca8 Profiling metrics: Buffer metric data writes on a per-line basis.
This is part of a series of changes to add metric charts in performance
benchmarks.

Because profiling metric data may be injected within container logs, it can
find itself surrounded by output from the container logs which are not
profiling metric data. When using regular byte-size-based buffering, this
can lead to lines being merged together with unrelated output, resulting in
corrupted data.

The new writer implementation instead buffers write on a per-line-number
basis. The buffer is flushed when a certain number of lines has been reached.
The contents are also prefixed and suffixed by `\n` to ensure the data does
not share a line with the rest of the logs.

PiperOrigin-RevId: 631213716
2024-05-06 16:06:21 -07:00
Etienne PerotandgVisor bot f629c1f0e0 Add a checksum to the end of the profiling metrics file.
This will allow us to check the integrity of the metrics data when read
out of a log file that may be polluted with other data, or truncated due
to overflowing a ringbuffer of logs somewhere in the logs pipeline.

This is part of a series of changes to add metric charts in performance
benchmarks.

PiperOrigin-RevId: 630487877
2024-05-03 13:51:35 -07:00
Etienne PerotandgVisor bot c8da73daaf Add option to dump profiling metrics within a container's stdout logs.
This is part of a series of changes to add metric charts in performance
benchmarks.

This change is useful to be able to extract profiling metric data easily
regardless of runtime configuration.

This change also changes where profiling metrics are initialized and
configured. They are now only part of `runsc boot`, rather than all `runsc`
invocations.

PiperOrigin-RevId: 629900287
2024-05-01 18:33:26 -07:00
Ayush RanjanandgVisor bot d4861911c2 Make atomicbitops.Bool savable.
Earlier the atomicbitops_state_autogen.go was not being built because it had
an impossible build condition: `(amd64 || arm64) && !amd64 && !arm64`.

This is a known deficiency in go_stateify tool. This was solved via having
two identical files like 32b_32bit.go and 32b_64bit.go. Just piggyback this.

This changes also enhances `atomicbitops.Bool` in the following ways:
- Added RacyLoad(), RacyStore() and CompareAndSwap() for Bool to bring it up to
  speed with the other types.
- Delegated the actual atomic operations work to the underlying Uint32.
- Cleaned up code with b32(); similar to what sync/atomic.Bool does.

PiperOrigin-RevId: 597607982
2024-01-11 11:24:32 -08:00
Konstantin BogomolovandgVisor bot 4120841184 Enable easy creation of independent profiling metrics.
When using conditionally compiled metrics there was only one go_tag to rule them
all. That's kind of a shame because when profiling something specific it's
nicer to know that only your metrics that you care about are compiled in and
metrics that you don't care about aren't.

This CL makes it easy to create new profiling go_tags, by abstracting the
profiling metric init functions under two builder structs: RealMetricBuilder
and FakeMetricBuilder; these builder structs are the only things that need
to change between the metrics-ON or OFF versions of conditional metric files
(aside from the go_tag controlling conditional compilation of course).
Ideally having to create these files manually wouldn't be necessary at all,
and we could use a go_template build rule instead, but that doesn't support
replacing go:build tags AFAIK.

PiperOrigin-RevId: 571153131
2023-10-05 15:56:37 -07:00
Konstantin BogomolovandgVisor bot 440b37a5c1 Add profiling metric flags to output metric data to local TSV file.
The idea behind conditionally compiled metrics originally was to use them in
hotpaths for profiling purposes. This CL makes that possible by outputting
declared metrics in TSV format, which can be used to track custom events at
runtime in relatively high resolution.

Usage:
    1. Optionally enable compilation of runsc conditionally-compiled metrics
       by passing in condmetric_profiling to the Go tags.
    2. Add these flags to runsc:
    - [Required] --profiling-metrics-log=/tmp/some.csv
    - [Optional] --profiling-metrics=/task/syscalls,/task/faults
      - If this flag is not specified it will monitor all
        conditionally-compiled metrics by default.
    - [Optional] --profiling-metrics-rate-us=10000

Some future improvements:
    - Flag to output a metric-difference between timestamps instead of
      constant accumulation.
    - Output a gnuplot command along with the data.
    - Current monitoring resolution is limited by what time.Sleep allows.
      This can be overcome by spinning/yielding when lower monitoring
      rates are requested.

PiperOrigin-RevId: 560849611
2023-08-28 16:28:09 -07:00
Etienne PerotandgVisor bot 0d246232ab gVisor metric library: Verify path-style metric names.
The `unimplemented_syscalls` metric did not conform (whoops), so fix that one.

PiperOrigin-RevId: 539767799
2023-06-12 14:53:17 -07:00
Etienne PerotandgVisor bot 32f5257ab7 gVisor metrics: Make debugging log lines more helpful.
When debugging is enabled, metric updates are written to the log as they
are emitted. This change adds metric fields to this log, and formats values
better between integers-typed and distribution-typed metrics.

Sample output:

```
metric.go] Emitting metrics:
[...]
metric.go]   Metric /netstack/udp/packets_sent: 0
metric.go]   Metric /netstack/udp/receive_buffer_errors: 0
metric.go]   Metric /netstack/udp/unknown_port_errors: 0
metric.go]   Metric /trace/sessions_created: 0
metric.go]   Metric unimplemented_syscalls[sysno=334]: 8
```

PiperOrigin-RevId: 539206126
2023-06-09 16:35:57 -07:00
Etienne PerotandgVisor bot f8d8cc45ab gVisor metrics library: Add distribution statistics to Prometheus Histogram.
This plumbs the distribution statistics out to the data consumed from the
gVisor sandbox process by the `runsc metric-server` process.

PiperOrigin-RevId: 537990236
2023-06-05 15:04:15 -07:00