feat: new profiling and instrumentation utility crates stacks-profiler & stacks-profiler-macros#6905
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #6905 +/- ##
===========================================
- Coverage 72.67% 72.34% -0.33%
===========================================
Files 411 425 +14
Lines 221663 223697 +2034
Branches 0 338 +338
===========================================
+ Hits 161086 161844 +758
- Misses 60577 61853 +1276
... and 313 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds two new workspace crates (stacks-profiler and stacks-profiler-macros) providing a lightweight, thread-local hierarchical span profiler with sampling, tagging, records/counters, and tree printing—intended for instrumentation/benchmarking usage and future wiring into runtime paths.
Changes:
- Introduces the core profiler implementation (TLS state/arena, span lifecycle, CPU-time support) plus printing utilities.
- Adds ergonomic instrumentation macros (
span!,measure!,record!,counter_add!, and conditional variants) and a#[profile]proc-macro. - Adds integration tests, examples, benchmarks, and wires the new crates + dependencies into the workspace/config.
Reviewed changes
Copilot reviewed 17 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
stacks-profiler/src/lib.rs |
Core profiler API, TLS state wiring, span/guard implementation, tag interning. |
stacks-profiler/src/macros.rs |
Defines span!/measure!/record/counter macros and conditional variants. |
stacks-profiler/src/state.rs |
Per-thread arena/stack model and results materialization. |
stacks-profiler/src/types.rs |
Record/counter/tag core value types and conversions. |
stacks-profiler/src/platform.rs |
Platform-specific per-thread CPU-time implementation. |
stacks-profiler/src/print.rs |
Tree formatter trait + default ANSI pretty-printer implementation. |
stacks-profiler/tests/integration.rs |
Integration coverage for nesting, sampling, suppression, count-only, panic safety, threading isolation. |
stacks-profiler/examples/basics.rs |
Basic end-to-end usage example of spans/measure/#[profile]. |
stacks-profiler/examples/aggregation.rs |
Example demonstrating aggregation + sampling modifiers. |
stacks-profiler/examples/cpu_vs_wait.rs |
Example showcasing wall vs CPU vs wait and metadata attachment. |
stacks-profiler/benches/overhead.rs |
Criterion benchmarks for overhead and sampling modes. |
stacks-profiler/README.md |
Crate-level documentation and usage reference. |
stacks-profiler/Cargo.toml |
New profiler crate manifest and deps. |
stacks-profiler-macros/src/lib.rs |
#[profile] proc-macro implementation (sync-only; async compile-fail). |
stacks-profiler-macros/Cargo.toml |
Proc-macro crate manifest and deps. |
Cargo.toml |
Adds new workspace members and shared workspace dependencies for profiler + macro deps. |
Cargo.lock |
Locks newly introduced dependencies. |
.cargo/config.toml |
Extends clippy-stacks alias to include the new crates. |
.gitignore |
Adds .vite ignore entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
benjamin-stacks
left a comment
There was a problem hiding this comment.
This looks really really great.
I still want to have a closer look at all the meta-programming (I'm not very familiar with macro writing yet) and the timing implementation, but I really like the surface API.
I've left a few small notes on that area, but nothing huge.
I'm really looking forward to using this. We built a very similar thing at Stack Overflow many years ago (https://miniprofiler.com/), and it's super useful to this day.
There was a problem hiding this comment.
LGTM!
I’ve added a number of minor comments and sanity checks.
One additional point to consider is the placement of these new crates. Should we move them to the contrib folder? If we decide to keep them in their current location, we should verify whether they are "covered" by the Bug Bounty Program, since the contrib folder is entirely excluded.
A third alternative would be to move it to a completely new project, as a separate open-source project. It might be useful in other Rust projects, far away from the Stacks ecosystem. |
Sure, that could work as well. As a starting point, we could add it under one of our organizations. We’ve already taken a similar approach with a couple of utilities, for example: We might have more flexibility placing it under the This would also avoid “burdening” the main repository with additional packages that are general purpose. |
Coverage Report for CI Build 26634242353Coverage increased (+0.09%) to 85.803%Details
Uncovered Changes
Coverage Regressions6662 previously-covered lines in 121 files lost coverage.
Coverage Stats
💛 - Coveralls |
|
Pushed a suite of tests to bump coverage (including silly |
benjamin-stacks
left a comment
There was a problem hiding this comment.
Great work! And after using it for quite a bit (with stacks-bench), I can't wait to have this merged.
One thing that I noticed while doing that: All the feature = "profiler" config attributes are pretty annoying, and some of the macros might not be usable at all.
A nice follow-up might be to have a mechanism in stacks-profiler itself which makes all the functionality no-op unless configured otherwise.
That something for later though. Let's ship this!
federico-stacks
left a comment
There was a problem hiding this comment.
LGTM!
heads-up: so unit tests jobs are failing due to missing cache entries. Probably a full CI workflow re-run is needed.
9ad6fde
…t together with nextest
Co-authored-by: Federico De Felici <234774522+federico-stacks@users.noreply.github.com>
Description
Introduces a new lightweight profiler for targeted instrumentation and result extraction, intended primarily for benchmarking/instrumentation builds, and to be feature-gated when wired into runtime paths. This profiler is used extensively by the
stacks-benchtool (follow-up PR).The motivation behind a custom implementation was that none of the existing instrumentation/profiling crates provided the level of control and detail which
stacks-benchneeded, and I also wanted it to be as slim and low-overhead as possible while providing ergonomic primitives to help minimize profiling clutter in core code.This PR adds two new workspace crates:
stacks-profiler: thread-local profiling library for hierarchical spans, wall/CPU/wait timing, tags, records, and counters.stacks-profiler-macros: procedural macro crate for profiler ergonomics, including#[profile](re-exported bystacks-profiler).These crates are added at workspace root (rather than
contrib) because they are intended dependencies of root crates.No existing runtime paths are wired yet, so this PR does not alter any existing behavior.
Included in this PR:
span!,measure!,record!,counter_add!, plus conditional*_if!variants.#[profile]attribute macro (sync functions only;async fnis compile-fail).Non-Goals for this PR:
stackslib,clarity, etc. (follow-up PRs).#[profile]support forasyncfunctions (not currently used in the main codebase).Applicable issues
#118.Checklist