You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
let (runtime, _guard) =TracedRuntime::build_and_start(builder, Box::new(writer))?;
22
+
let (runtime, _guard) =TracedRuntime::build_and_start(builder, writer)?;
23
23
24
24
runtime.block_on(async {
25
25
// your async code here
@@ -70,7 +70,7 @@ Use `handle.spawn()` instead of `tokio::spawn()`:
70
70
# fn main() -> std::io::Result<()> {
71
71
# let writer = RotatingWriter::new("/tmp/t.bin", 1024, 4096)?;
72
72
# let builder = tokio::runtime::Builder::new_multi_thread();
73
-
let (runtime, guard) = TracedRuntime::build_and_start(builder, Box::new(writer))?;
73
+
let (runtime, guard) = TracedRuntime::build_and_start(builder, writer)?;
74
74
let handle = guard.handle();
75
75
76
76
runtime.block_on(async {
@@ -100,7 +100,7 @@ On non-Linux platforms these fields are zero.
100
100
101
101
With the `cpu-profiling` feature, you can enable `perf_event_open`-based CPU sampling. This gives two key pieces of data:
102
102
1. Stack traces when code was running on the CPU — aka flamegraphs
103
-
2.2.Stack traces when the kernel _descheduled_ your thread. For example, if you use `std::thread::sleep` in your future or are seeing `std::sync::Mutex` contention, this will allow you to see precisely where this is happening in async code.
103
+
2. Stack traces when the kernel _descheduled_ your thread. For example, if you use `std::thread::sleep` in your future or are seeing `std::sync::Mutex` contention, this will allow you to see precisely where this is happening in async code.
104
104
105
105
Both of these events are tied to the precise instant and thread that they happened on, so you can compare what was different between degraded and normal performance.
106
106
@@ -117,7 +117,7 @@ let (runtime, guard) = TracedRuntime::builder()
@@ -126,6 +126,30 @@ let (runtime, guard) = TracedRuntime::builder()
126
126
127
127
This pulls in [`dial9-perf-self-profile`](/perf-self-profile) for `perf_event_open` access. It records `CpuSample` events with full callchains and `CallframeDef` / `ThreadNameDef` metadata for offline symbolization.
128
128
129
+
#### Requirements
130
+
131
+
**Frame pointers**: CPU profile stack traces rely on frame-pointer-based unwinding. Compile your application with frame pointers enabled, otherwise stack traces will be truncated or missing:
132
+
133
+
```toml
134
+
# .cargo/config.toml
135
+
[build]
136
+
rustflags = ["-C", "force-frame-pointers=yes"]
137
+
```
138
+
139
+
**`perf_event_paranoid`**: CPU profiling features require `perf_event_paranoid` ≤ 2 for sampling, and ≤ 1 for scheduler event tracking (`with_sched_events`):
140
+
141
+
```bash
142
+
# check current value
143
+
cat /proc/sys/kernel/perf_event_paranoid
144
+
145
+
# allow CPU sampling and scheduler event tracking
146
+
sudo sysctl kernel.perf_event_paranoid=1
147
+
```
148
+
149
+
#### Diagnosing long polls with CPU samples
150
+
151
+
Because CPU samples are tagged with the worker thread they were collected on, and the trace records which task is being polled on each worker at each instant, the viewer can correlate samples with individual polls. When a poll takes an unusually long time (a "long poll"), the CPU samples collected during that poll show you exactly what code was running — expensive serialization, accidental blocking I/O, lock contention, etc. In the trace viewer, click on a long poll to see its flamegraph, or shift+drag to aggregate CPU samples across a time range.
152
+
129
153
## Getting started
130
154
131
155
`TracedRuntime::build` returns a `(Runtime, TelemetryGuard)`. The guard owns the flush thread and provides a `TelemetryHandle` for enabling/disabling recording at runtime:
@@ -137,7 +161,7 @@ This pulls in [`dial9-perf-self-profile`](/perf-self-profile) for `perf_event_op
137
161
# let builder = tokio::runtime::Builder::new_multi_thread();
138
162
let (runtime, guard) = TracedRuntime::builder()
139
163
.with_task_tracking(true)
140
-
.build(builder, Box::new(writer))?;
164
+
.build(builder, writer)?;
141
165
142
166
// start disabled, enable later
143
167
guard.enable();
@@ -151,7 +175,7 @@ handle.disable();
151
175
152
176
### Writers
153
177
154
-
`RotatingWriter` rotates files and evicts old ones to stay within a total size budget. `SimpleBinaryWriter` writes a single file with no size management, useful for quick experiments.
178
+
`RotatingWriter` rotates files and evicts old ones to stay within a total size budget. For quick experiments, `RotatingWriter::single_file(path)` writes a single file with no rotation.
0 commit comments