Skip to content

Commit 2ca0131

Browse files
committed
Rename SamplyInterval to SamplyTimer
This commit renames all instances of SamplyInterval or samply_interval to use the word "timer" instead. After writing a lot of documentation and examples, I have decided that I think "timer" feels more ergonomic to use as an abstraction, even though it emits an interval type marker. This feels like too much work to interactive rebase back into the history of this stack, so I'm appending it on.
1 parent 2c1d025 commit 2ca0131

File tree

9 files changed

+297
-210
lines changed

9 files changed

+297
-210
lines changed

samply-markers/README.md

Lines changed: 94 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,38 @@
22

33
Emit profiler markers that [samply] records and displays in the [Firefox Profiler](https://profiler.firefox.com/) UI.
44

5+
## Quick Start Demo
6+
7+
The following Fibonacci Sequence example demonstrates recursive function call tracking.
8+
9+
The [`samply_measure!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_measure.html) macro emits an interval marker
10+
for each recursive call, allowing the profiler to display the complete call tree with timing information for every `fib(n)` invocation.
11+
12+
* [Example profile](https://share.firefox.dev/47ZPJfr)
13+
14+
```rust
15+
use samply_markers::prelude::*;
16+
17+
// Recursive Fibonacci Sequence
18+
fn fib(n: u64) -> u64 {
19+
samply_measure!({
20+
match n {
21+
0 => 0,
22+
1 => 1,
23+
_ => fib(n - 1) + fib(n - 2),
24+
}
25+
}, marker: {
26+
name: format!("fib({n})"),
27+
})
28+
}
29+
30+
fn main() {
31+
let n = 10;
32+
let value = fib(n);
33+
println!("fib({n}) = {}", value);
34+
}
35+
```
36+
537
## Project Configuration
638

739
<br> **1)** Add [samply-markers](https://crates.io/crates/samply-markers) as a dependency to your project's `Cargo.toml`.
@@ -17,8 +49,8 @@ samply-markers = "{version}"
1749
> Samply markers are designed to no-op by default, so they must be explicitly enabled in order
1850
> to see them in profiles.
1951
>
20-
> * Using samply-markers has effectively zero cost when not enabled.
21-
> * Using samply-markers does not pull in any additional dependencies when not enabled.
52+
> * Using [samply-markers](https://crates.io/crates/samply-markers) has effectively zero cost when not enabled.
53+
> * Using [samply-markers](https://crates.io/crates/samply-markers) does not pull in any additional dependencies when not enabled.
2254
2355
```toml
2456
[features]
@@ -36,22 +68,22 @@ inherits = "release"
3668
debug = true
3769
```
3870

39-
<br> **4)** Import the [`samply_markers::prelude`](https://docs.rs/samply-markers/latest/samply_markers/prelude/) to get started adding markers to your code.
40-
41-
<br> **5)** Build your project for profiling, then record the resulting binary with [samply] to capture the emitted markers.
71+
<br> **4)** Build your project for profiling, then record the resulting binary with [samply] to process the emitted markers.
4272

4373
```text
4474
cargo build --profile profiling --features samply-markers
4575
samply record target/profiling/{binary}
4676
```
4777

48-
## API
78+
## Public API
4979

50-
#### The `samply_marker!` macro
80+
### The [`samply_marker!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_marker.html) macro
5181

52-
The [`samply_marker!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_marker.html) macro is the foundational way to emit profiler markers. It creates and emits a [`SamplyMarker`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyMarker.html) at the current location in your code, supporting both instant markers (a single point in time) and interval markers (a span of time).
82+
The [`samply_marker!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_marker.html) macro is the foundational way to emit profiler markers.
83+
It creates and emits a [`SamplyMarker`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyMarker.html) at the current location in your code,
84+
supporting both instant markers (a single point in time) and interval markers (a span of time).
5385

54-
**Instant Marker**
86+
#### Instant Marker
5587

5688
An instant marker marks a specific point in time:
5789

@@ -62,11 +94,11 @@ fn process_request(request_id: u32) {
6294
// Emit an instant marker at this exact moment
6395
samply_marker!({ name: format!("processing request {request_id}") });
6496

65-
// ... process the request
97+
// ... process the request.
6698
}
6799
```
68100

69-
**Interval Marker**
101+
#### Interval Marker
70102

71103
An interval marker spans from a start time to the current time using [`SamplyTimestamp`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyTimestamp.html):
72104

@@ -76,10 +108,10 @@ use samply_markers::prelude::*;
76108
fn query_database(query: &str) -> Vec<String> {
77109
let start = SamplyTimestamp::now();
78110

79-
// ... execute the database query
80-
let results = vec![]; // Placeholder for actual results
111+
// ... execute the database query.
112+
let results = vec![]; // Placeholder for actual results.
81113

82-
// Emit an interval marker from start to now
114+
// Emit an interval marker from start to now.
83115
samply_marker!({
84116
name: format!("database query: {query}"),
85117
start_time: start,
@@ -91,69 +123,80 @@ fn query_database(query: &str) -> Vec<String> {
91123

92124
---
93125

94-
#### The `samply_interval!` macro
126+
### The [`samply_timer!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_timer.html) macro
95127

96-
While `samply_marker!` requires manually capturing a [`SamplyTimestamp`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyTimestamp.html) for interval markers, the [`samply_interval!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_interval.html) macro simplifies this pattern by wrapping the timestamp in a scoped RAII object. It creates a [`SamplyInterval`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyInterval.html) that captures the start time when created and automatically emits the interval marker when dropped at the end of its scope.
128+
While [`samply_marker!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_marker.html) requires manually providing a
129+
[`SamplyTimestamp`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyTimestamp.html) for interval markers,
130+
the [`samply_timer!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_timer.html) macro simplifies this pattern
131+
by wrapping the timestamp in a scoped RAII object. It creates a [`SamplyTimer`](https://docs.rs/samply-markers/latest/samply_markers/marker/struct.SamplyTimer.html)
132+
that registers the time it was created and automatically emits the interval marker when dropped at the end of its scope.
97133

98-
**Automatic Interval**
134+
#### Automatic Interval
99135

100-
The interval emits when the variable is dropped:
136+
The interval marker emits when the timer is dropped:
101137

102138
```rust
103139
use samply_markers::prelude::*;
104140

105141
fn expensive_computation() {
106-
let _timer = samply_interval!({ name: "expensive computation" });
142+
let _timer = samply_timer!({ name: "expensive computation" });
107143

108-
// ... perform expensive work
144+
// ... perform expensive work.
109145

110-
// The interval is automatically emitted here when _timer is dropped
146+
// The interval marker is automatically emitted here when _timer is dropped.
111147
}
112148
```
113149

114-
**Early Emit**
150+
#### Early Emit
115151

116-
You can explicitly emit the interval before the end of the scope:
152+
You can explicitly emit the interval marker before the end of the scope:
117153

118154
```rust
119155
use samply_markers::prelude::*;
120156

121157
fn process_with_cleanup() {
122-
let timer = samply_interval!({ name: "core processing" });
158+
let timer = samply_timer!({ name: "core processing" });
123159

124-
// ... perform core processing work
160+
// ... perform core processing work.
125161

126-
// Emit the interval now, excluding cleanup from the measurement
162+
// Emit the interval marker now, excluding cleanup from the measurement.
127163
timer.emit();
128164

129-
// ... perform cleanup tasks (not included in the interval)
165+
// ... perform cleanup tasks (not included in the interval marker).
130166

131-
// The interval will not emit a second time when dropped
167+
// The interval marker will not emit a second time when dropped.
132168
}
133169
```
134170

135171
---
136172

137-
#### The `samply_measure!` macro
173+
### The [`samply_measure!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_measure.html) macro
174+
175+
Building on the scoped approach of [`samply_timer!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_timer.html),
176+
the [`samply_measure!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_measure.html) macro further simplifies profiling
177+
by eliminating the need to create a scoped timer yourself. Instead, you wrap a code block, then its execution time is automatically measured with an interval marker.
138178

139-
Building on the scoped approach of `samply_interval!`, the [`samply_measure!`](https://docs.rs/samply-markers/latest/samply_markers/macro.samply_measure.html) macro further simplifies profiling by eliminating the need to create a scoped object yourself. Instead, you wrap a code block, and the macro measures its execution time and emits an interval marker, while preserving the block's return value.
179+
#### Synchronous Example
140180

141-
**Synchronous Example**
181+
The value of the block expression is returned:
142182

143183
```rust
144184
use samply_markers::prelude::*;
145185

146-
fn compute_fibonacci(n: u32) -> u64 {
186+
fn compute_sum(values: &[i32]) -> i32 {
147187
samply_measure!({
148-
// ... compute fibonacci
149-
42 // Return value is preserved
188+
values.iter().sum()
150189
}, marker: {
151-
name: format!("fibonacci({n})"),
190+
name: "compute sum",
152191
})
153192
}
193+
194+
let values = vec![1, 2, 3, 4, 5];
195+
let result = compute_sum(&values);
196+
assert_eq!(result, 15);
154197
```
155198

156-
**With `?` Operator**
199+
#### With `?` Operator
157200

158201
The block's control flow is preserved, including early returns:
159202

@@ -162,12 +205,12 @@ use samply_markers::prelude::*;
162205

163206
fn parse_and_validate(data: &str) -> Result<u32, String> {
164207
samply_measure!({
165-
// The ? operator works normally and returns from the function
208+
// The ? operator works normally and returns from the function.
166209
let parsed = data.parse::<u32>()
167210
.map_err(|e| format!("parse error: {e}"))?;
168211

169212
if parsed > 100 {
170-
return Err("value too large".to_string());
213+
return Err(String::from("value too large"));
171214
}
172215

173216
Ok(parsed)
@@ -177,7 +220,7 @@ fn parse_and_validate(data: &str) -> Result<u32, String> {
177220
}
178221
```
179222

180-
**Asynchronous Example**
223+
#### Asynchronous Example
181224

182225
For async code, use `async` before the block and `.await` after the macro:
183226

@@ -186,22 +229,28 @@ use samply_markers::prelude::*;
186229

187230
async fn process_data(data_id: u64) -> Result<String, String> {
188231
let result = samply_measure!(async {
189-
// The async block is measured from start to completion
232+
// The async block is measured from start to completion.
190233
let data = simulate_async_work().await?;
191234
let processed = format!("Processed: {data} (id: {data_id})");
192235
Ok(processed)
193236
}, marker: {
194237
name: format!("process data {data_id}"),
195238
})
196-
.await?; // Don't forget the .await after the macro
239+
.await?;
197240

198241
Ok(result)
199242
}
200243
```
201244

202245
## Examples
203246

204-
Here's a complete example demonstrating all three macros in context:
247+
Example profiles of the code below:
248+
249+
* [Ubuntu](https://share.firefox.dev/4qZ7yUj)
250+
* [macOS](https://share.firefox.dev/49Au7J1)
251+
* Windows (not yet supported)
252+
253+
Here's a complete example demonstrating everything in context:
205254

206255
```rust
207256
use samply_markers::prelude::*;
@@ -232,9 +281,9 @@ async fn fetch_url(url: &str) -> (String, Option<String>) {
232281

233282
#[tokio::main]
234283
async fn main() {
235-
// Create an interval marker that will span the entirety of main()
236-
// The marker will emit when it is dropped at the end of the scope.
237-
let _main_interval = samply_interval!({ name: "main()" });
284+
// Create a timer that will span the entirety of main().
285+
// The timer will emit an interval marker when it is dropped at the end of the scope.
286+
let _main_timer = samply_timer!({ name: "main()" });
238287

239288
println!("\nStarting samply-markers demo...\n");
240289

@@ -279,10 +328,4 @@ async fn main() {
279328
}
280329
```
281330

282-
## Example Profiles
283-
284-
* [Ubuntu](https://share.firefox.dev/3LCG4DQ)
285-
* [macOS](https://share.firefox.dev/47SmHOr)
286-
* Windows is not yet supported.
287-
288331
[samply]: https://github.com/mstange/samply?tab=readme-ov-file#samply

0 commit comments

Comments
 (0)