Model or dataset
pawurb/hotpath-rs avatar
pawurb/hotpath-rs

hotpath-rs: a feature-gated Rust profiler for timing, allocations and async data flow

Rust profiler for CPU, memory, SQL, HTTP, and async performance, with Prometheus and Grafana support.

1,735 stars52 forksRustMIT

At a glance

What is it?
hotpath-rs instruments functions, channels, locks, SQL and HTTP calls behind a disabled-by-default Cargo feature, then reports timings, allocation counts and Prometheus metrics. It suits Rust services whose bottlenecks are spread across sync code and async I/O.
Who is it for?
Adopt hotpath-rs when you need per-function timings, allocation counts and channel or lock metrics from a Rust service, and you are willing to add a feature-gated dependency plus attribute macros to the code you want measured. Skip it if you want a sampling profiler that attaches to an unmodified binary, or if you cannot rebuild with the hotpath feature.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What hotpath-rs measures that a plain timer does not

The problem hotpath-rs targets is attribution. A stopwatch around a request handler tells you the handler is slow; it does not tell you whether the time went to a SQL query, a channel send, a lock wait, or a function that allocates on every call. The README frames the goal as distinguishing functions that are slow because they wait on I/O from those that are CPU-intensive, and the feature list covers timing, CPU, memory allocation, futures, channels, streams, byte-level I/O, SQL queries for sqlx and Diesel, HTTP calls for reqwest and ureq, HTTP server routes for axum, Mutex and RwLock contention, and Tokio runtime workers and queues. The audience is Rust developers who already suspect where the problem is and want numbers per function, per channel or per query rather than a flame graph of the whole process. The repository layout backs this up: the workspace contains separate test crates for sqlx 0.8 and 0.9, reqwest 0.12 and 0.13, ureq, axum, diesel, tokio, smol, futures, and five different channel implementations, which suggests the integration surface is intentionally wide and each supported library version is exercised on its own.

How the macros and feature gates fit together

The mechanism is attribute macros plus Cargo features. You annotate a function with #[hotpath::measure], annotate main with #[hotpath::main], and the macros record call counts, average, P95 and total time per function. The README notes that when the program uses tokio, #[tokio::main] must be placed first and #[hotpath::main] second. Blocks can be measured without a separate function via hotpath::measure_block!("custom_block", { ... }), which is how the README's example captures a sleep that is not wrapped in its own function. The feature design is the part worth reading carefully: the Cargo.toml snippet declares hotpath as an optional dependency and defines features hotpath, hotpath-cpu, hotpath-alloc and hotpath-prometheus that forward to the corresponding crate features. The README states that this ensures no compile time or runtime overhead unless explicitly enabled, that all library dependencies are optional, and that all macros are noop unless profiling is enabled. That is a real design commitment rather than a slogan, because it means the instrumentation call sites can stay in the code permanently while release builds compile them away. The output is a table per category, with columns for calls, average, P95, total and percentage of total, and the README's sample report shows a header line such as [hotpath] 1.20s | timing, alloc, threads followed by per-function rows. For longer-running services the same data can be exported to Prometheus and rendered in Grafana, and there is a live TUI dashboard for real-time inspection. The repository also lists an MCP server so AI agents can query profiling data in real time.

Installing hotpath-rs and getting a first timing report

The README presents two paths. The recommended one installs the hotpath CLI and lets an AI coding agent wire the instrumentation into your project:

bash
cargo install hotpath --version '^0.25'
hotpath init --agent claude # or --agent codex / --agent opencode

According to the README, hotpath init downloads the hotpath_init agent skill from GitHub and starts an interactive session with Claude Code, Codex or OpenCode using that skill as setup instructions. The agent inspects the project, adds the feature-gated dependency, instruments main plus a starting set of functions, channels and locks, and verifies the project compiles with profiling both enabled and disabled. Each edit goes through the agent's normal permission prompts, and the command requires curl plus one of the claude, codex or opencode CLIs on PATH. The README also documents using the skill without the CLI, by copying it to ~/.claude/skills/hotpath_init/SKILL.md and running /hotpath_init in a Claude Code session.

The manual path adds the dependency and the feature forwarding to Cargo.toml:

toml
[dependencies]
hotpath = "0.25"

[features]
hotpath = ["hotpath/hotpath"]
hotpath-cpu = ["hotpath/hotpath-cpu"]
hotpath-alloc = ["hotpath/hotpath-alloc"]
hotpath-prometheus = ["hotpath/hotpath-prometheus"]

Then annotate the functions you care about and main itself:

rust
#[hotpath::measure]
fn sync_function(sleep: u64) {
    std::thread::sleep(Duration::from_nanos(sleep));
    let vec1 = vec![1, 2, 3];
    std::hint::black_box(&vec1); // force mem allocation
}

#[tokio::main]
#[hotpath::main]
async fn main() {
    // ...
}

Run with the features enabled:

bash
cargo run --features='hotpath,hotpath-alloc'

On exit the program prints a report with timings, memory allocations and thread usage metrics. In the README's example the report header reads [hotpath] 1.20s | timing, alloc, threads, and the timing table lists each annotated function with its call count, average, P95 and share of total time.

Where hotpath-rs stops being the right tool

The cost of the design is that instrumentation is opt-in per call site. A function you did not annotate produces no row, so the first profiling session tends to under-report: the table shows the functions you remembered to mark and nothing about the ones you forgot. The README's own example makes this visible, since the walkthrough starts from a single annotated main and a couple of annotated helpers. If you need a profile of an unmodified binary, or of a dependency you cannot edit, this is the wrong instrument. The same applies to release binaries you did not build with the feature enabled, because the macros compile to noops without it. There is also a version-coupling constraint worth naming: the workspace carries separate test crates for sqlx 0.8 and 0.9 and for reqwest 0.12 and 0.13, which indicates that support is version-specific rather than generic across any crate that happens to make SQL or HTTP calls. If your project pins a version outside the supported set, the SQL or HTTP attribution may not apply. The README does not document rollback or removal of the instrumentation, so the practical path back is deleting the attributes and the feature entries yourself.

hotpath-rs against a sampling profiler such as Samply

The obvious alternative for Rust is a sampling profiler in the Samply family, which attaches to a running process and samples stacks without code changes. The difference in approach is not cosmetic. Sampling gives you a whole-process picture including code you did not instrument, at the cost of statistical noise and no notion of a channel's queue depth or a SQL query's source function. hotpath-rs does the opposite: it records exact call counts, averages and P95 per annotated function, and it can attribute a SQL query or an HTTP call back to the function that issued it, which the README shows as automatic source function attribution in the SQL report. It also reports things a stack sampler cannot see directly, such as bytes and transfer rates for an I/O stream, max queue depth for a channel, and Mutex or RwLock wait time. What you give up is coverage of uninstrumented code and the ability to profile a binary you cannot rebuild. The two are complementary in practice: sampling to find the neighborhood, hotpath-rs to measure the specific function, channel or query once you know where to look.

Maintenance, licence and the cost of upgrading

The last push to the repository was on 2026-09-09, and the most recent release listed is v0.25.1 from 2026-09-05, following v0.25.0 on 2026-09-03 and v0.24.0 on 2026-08-22. The project is not archived. Release cadence in that window is frequent, and the version numbering is pre-1.0, so minor bumps can carry changes. The README pins the CLI install to cargo install hotpath --version '^0.25' and the dependency example to hotpath = "0.25", which means the practical upgrade unit is the 0.25 line rather than the whole 0.x range. The repository includes a CHANGELOG.md and a cliff.toml, so release notes are generated, and the justfile exposes bench, compare, compare_meta and test_all recipes that run the workspace test suites; the test_all recipe invokes cargo test with --features hotpath across many per-integration test targets. Because instrumentation lives in your source, an upgrade can require touching annotated call sites, not just the lockfile. The licence is MIT, stated in the repository and in a LICENSE.txt file at the top level. MIT is permissive and imposes no copyleft obligation on your code, but this is a description of the licence identifier, not legal advice.

What to check before adding hotpath-rs to a service

Two things decide whether this fits. First, whether the parts of the system you suspect can be annotated at all: a handler you own is easy, a query issued deep inside a third-party crate is not. Second, whether the compile-with-and-without check actually passes in your crate, because the feature forwarding in Cargo.toml is what keeps the noop guarantee intact and a mistake there is silent until a release build behaves differently from a debug build. The repository's justfile gives a starting point for that verification, since test_all runs the workspace tests with --features hotpath. For a service already exporting Prometheus metrics, the hotpath-prometheus feature is the lower-friction route: you keep your existing dashboards and add profiling series to them instead of introducing a second place to look.

Editorial conclusion

Adopt hotpath-rs when you need per-function timings, allocation counts and channel or lock metrics from a Rust service, and you are willing to add a feature-gated dependency plus attribute macros to the code you want measured. Skip it if you want a sampling profiler that attaches to an unmodified binary, or if you cannot rebuild with the hotpath feature. Before committing, verify that the feature-gated dependency and the #[hotpath::main] attribute compile in your own crate with the feature both on and off, since that is the step the agent-assisted setup claims to check for you.

Frequently asked questions

Does hotpath-rs add overhead to my release build?

The README states that the library has no compile time or runtime overhead unless the hotpath feature is explicitly enabled, that all its dependencies are optional, and that all macros are noop unless profiling is enabled. The Cargo.toml example in the README is written specifically to keep it that way.

Which async runtimes and libraries does hotpath-rs support?

The README lists support for futures, channels and streams, Tokio runtime monitoring, SQL profiling for sqlx and Diesel, HTTP call profiling for reqwest and ureq, and HTTP server profiling for axum. The workspace contains separate test crates for tokio and smol, for sqlx 0.8 and 0.9, and for reqwest 0.12 and 0.13.

Can I try hotpath-rs without installing anything?

The README offers a TUI demo over SSH with no installation required, using the command ssh demo.hotpath.rs. That connects to a live dashboard showing real-time performance and async data flow metrics.

How do I get hotpath-rs to configure itself in my project?

Install the CLI with cargo install hotpath --version '^0.25' and run hotpath init --agent claude, --agent codex or --agent opencode. According to the README, the command downloads the hotpath_init agent skill and starts an interactive session that adds the dependency, instruments main and a starting set of functions, channels and locks, and verifies compilation with profiling enabled and disabled. It requires curl and the matching agent CLI on PATH.

Official sources

  1. License: MIT
  2. pawurb/hotpath-rs on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pawurb-hotpath-rs.svg)](https://hysenlabs.com/projects/pawurb-hotpath-rs)