Skip to content

feat: new profiling and instrumentation utility crates stacks-profiler & stacks-profiler-macros#6905

Merged
cylewitruk-stacks merged 30 commits into
stacks-network:developfrom
cylewitruk-stacks:feat/stacks-profiler
Jun 1, 2026
Merged

feat: new profiling and instrumentation utility crates stacks-profiler & stacks-profiler-macros#6905
cylewitruk-stacks merged 30 commits into
stacks-network:developfrom
cylewitruk-stacks:feat/stacks-profiler

Conversation

@cylewitruk-stacks

@cylewitruk-stacks cylewitruk-stacks commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

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-bench tool (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-bench needed, 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 by stacks-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:

  • Core profiler state/model and platform CPU-time support.
  • Instrumentation macros: span!, measure!, record!, counter_add!, plus conditional *_if! variants.
  • #[profile] attribute macro (sync functions only; async fn is compile-fail).
  • Crate docs/readme, examples, benchmarks, and integration/doctest coverage.

Non-Goals for this PR:

  • Wiring profiler calls into stackslib, clarity, etc. (follow-up PRs).
  • #[profile] support for async functions (not currently used in the main codebase).
  • Truly supporting Windows (I added a simple impl for completeness, but the timing resolution is coarse).

Applicable issues

  • Related to core epic #118.

Checklist

  • Test coverage for new or modified code paths
  • Changelog is updated

@CLAassistant

CLAassistant commented Feb 16, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codecov

codecov Bot commented Feb 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 40.63604% with 336 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.34%. Comparing base (0317850) to head (7ce2e88).
⚠️ Report is 933 commits behind head on develop.

Files with missing lines Patch % Lines
stacks-profiler/src/print.rs 0.00% 115 Missing ⚠️
stacks-profiler/src/lib.rs 49.28% 107 Missing ⚠️
stacks-profiler-macros/src/lib.rs 0.00% 54 Missing ⚠️
stacks-profiler/src/types.rs 0.00% 54 Missing ⚠️
stacks-profiler/src/state.rs 94.91% 6 Missing ⚠️
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     
Files with missing lines Coverage Δ
stacks-profiler/src/macros.rs 100.00% <100.00%> (ø)
stacks-profiler/src/platform.rs 100.00% <100.00%> (ø)
stacks-profiler/src/state.rs 94.91% <94.91%> (ø)
stacks-profiler-macros/src/lib.rs 0.00% <0.00%> (ø)
stacks-profiler/src/types.rs 0.00% <0.00%> (ø)
stacks-profiler/src/lib.rs 49.28% <49.28%> (ø)
stacks-profiler/src/print.rs 0.00% <0.00%> (ø)

... and 313 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0317850...7ce2e88. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread stacks-profiler/src/lib.rs
Comment thread stacks-profiler/src/lib.rs Outdated

@benjamin-stacks benjamin-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread stacks-profiler/src/lib.rs Outdated
Comment thread stacks-profiler/src/lib.rs Outdated
Comment thread stacks-profiler/src/lib.rs Outdated
Comment thread stacks-profiler/src/state.rs
Comment thread stacks-profiler/src/macros.rs
Comment thread stacks-profiler/src/macros.rs

@federico-stacks federico-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread stacks-profiler/src/print.rs Outdated
Comment thread stacks-profiler/src/state.rs Outdated
Comment thread stacks-profiler/src/lib.rs
Comment thread stacks-profiler/src/macros.rs
@benjamin-stacks

Copy link
Copy Markdown
Contributor

Should we move them to the contrib folder?

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.

Comment thread stacks-profiler-macros/src/lib.rs Outdated
Comment thread stacks-profiler/src/macros.rs Outdated
Comment thread stacks-profiler/src/macros.rs
Comment thread stacks-profiler/src/state.rs Outdated
@federico-stacks

Copy link
Copy Markdown
Contributor

Should we move them to the contrib folder?

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 stx-labs organization, as we did with pinny-rs.

This would also avoid “burdening” the main repository with additional packages that are general purpose.

@coveralls

coveralls commented May 22, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 26634242353

Coverage increased (+0.09%) to 85.803%

Details

  • Coverage increased (+0.09%) from the base build.
  • Patch coverage: 34 uncovered changes across 3 files (874 of 908 lines covered, 96.26%).
  • 6662 coverage regressions across 121 files.

Uncovered Changes

File Changed Covered %
stacks-profiler-macros/src/lib.rs 100 76 76.0%
stacks-profiler/src/print.rs 262 256 97.71%
stacks-profiler/src/lib.rs 292 288 98.63%
Total (7 files) 908 874 96.26%

Coverage Regressions

6662 previously-covered lines in 121 files lost coverage.

Top 10 Files by Coverage Loss Lines Losing Coverage Coverage
stackslib/src/config/mod.rs 376 68.96%
stackslib/src/net/mod.rs 311 77.88%
stackslib/src/chainstate/stacks/index/storage.rs 284 82.27%
stackslib/src/chainstate/stacks/miner.rs 258 83.12%
clarity/src/vm/database/clarity_db.rs 244 82.23%
stackslib/src/net/inv/epoch2x.rs 223 79.38%
stackslib/src/chainstate/stacks/db/transactions.rs 222 97.16%
stackslib/src/net/chat.rs 201 93.01%
stackslib/src/chainstate/stacks/db/mod.rs 196 86.23%
stackslib/src/core/mempool.rs 193 86.44%

Coverage Stats

Coverage Status
Relevant Lines: 224374
Covered Lines: 192519
Line Coverage: 85.8%
Coverage Strength: 18786691.84 hits per line

💛 - Coveralls

@cylewitruk-stacks

Copy link
Copy Markdown
Contributor Author

Pushed a suite of tests to bump coverage (including silly print.rs tests):

Filename                              Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
stacks-profiler-macros/src/lib.rs         163                 8    95.09%          11                 0   100.00%         100                 7    93.00%           0                 0         -
stacks-profiler/src/lib.rs                472                 8    98.31%          53                 0   100.00%         305                 6    98.03%           0                 0         -
stacks-profiler/src/macros.rs               2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
stacks-profiler/src/platform.rs            30                 1    96.67%           5                 0   100.00%          28                 1    96.43%           0                 0         -
stacks-profiler/src/print.rs              306                 7    97.71%          10                 0   100.00%         262                 6    97.71%           0                 0         -
stacks-profiler/src/state.rs              244                 4    98.36%          16                 0   100.00%         156                 1    99.36%           0                 0         -
stacks-profiler/src/types.rs              133                 2    98.50%          16                 0   100.00%          84                 0   100.00%           0                 0         -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                    1350                30    97.78%         112                 0   100.00%         936                21    97.76%           0                 0         -

@benjamin-stacks benjamin-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 federico-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

heads-up: so unit tests jobs are failing due to missing cache entries. Probably a full CI workflow re-run is needed.

Comment thread stacks-profiler/tests/trybuild.rs Outdated
Co-authored-by: Federico De Felici <234774522+federico-stacks@users.noreply.github.com>
Comment thread stacks-profiler/tests/trybuild.rs Outdated
@cylewitruk-stacks cylewitruk-stacks added this pull request to the merge queue Jun 1, 2026
Merged via the queue into stacks-network:develop with commit c25d820 Jun 1, 2026
219 checks passed
@cylewitruk-stacks cylewitruk-stacks deleted the feat/stacks-profiler branch June 1, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants