Profiling Rust: The Complete Guide - From SQL Queries to CPU Sampling
Keyboard shortcuts
Press ← or → to navigate between chapters
Press S or / to search in the book
Press ? to show this help
Press Esc to hide this help
Auto
Light
Rust
Coal
Navy
Ayu
Profiling Rust: The Complete Guide - From SQL Queries to CPU Sampling
Published: August 11, 2026
Reading time: 35 minutes
My goal with building hotpath-rs is to create an all-in-one Rust performance profiler - “that covers everyone’s use cases”. In this guide, I’ll walk through its current profiling capabilities with practical examples of finding and fixing real performance bottlenecks. We’ll look at different layers of a Rust application - from SQL queries, HTTP calls, and I/O to locks, memory allocations, and CPU usage - and discuss how to identify performance issues specific to each one. As hotpath-rs evolves with new features, I’ll keep this article updated to make it a comprehensive reference for profiling Rust.
Layers of performance optimization
Rust is rapidly evolving from its low-level systems programming roots into a general-purpose language. As a result, performance optimization is no longer just about CPU samples and flame graphs. An efficient Rust performance optimization workflow now requires insights into higher-level signals such as SQL queries, HTTP requests, async execution and I/O bottlenecks.
I’m ordering the sections of this guide by their potential return on investment. In many backend applications, optimizing SQL queries or parallelizing HTTP calls can yield better improvements than optimizing CPU usage. Low-level optimizations remain essential for CPU-bound or latency-critical code, but they’re often most effective after higher-level bottlenecks have been addressed.
To put this into perspective, optimizing a CPU hot path may save microseconds per operation, while eliminating an unnecessary database round trip or parallelizing independent HTTP calls can sometimes remove hundreds of milliseconds from a response time. That’s why this guide starts with higher layers of the stack and gradually works its way down to low-level optimizations.
Each layer comes with a practical code example: a sample performance bottleneck, the profiler report that exposes it, and a fix with a measurable impact confirmed by the before/after numbers.
Profiling SQL query performance
hotpath currently supports SQL tracing for sqlx, diesel, and toasty. See SQL tracing docs for details on how to enable it.
Let’s see it in action. We have a simple diesel schema: posts, each with multiple comments. We want to display a list of posts, each with the count of its comments. Here’s the naive implementation:
examples/n_plus_one_before.rs
#[hotpath::measure]<br>fn list_comments(<br>conn: &mut SqliteConnection,<br>) -> Result, Box> {<br>let all_posts: Vec = posts::table.load(conn)?;
let mut result = Vec::with_capacity(all_posts.len());<br>for post in all_posts {<br>let post_comments: Vec = comments::table<br>.filter(comments::post_id.eq(post.id))<br>.load(conn)?;<br>result.push((post.title, post_comments.len()));<br>Ok(result)<br>The database is seeded with 20 posts, 5 comments each. Let’s profile it by running:
cargo run --release -p test-diesel --example n_plus_one_before --features hotpath
timing - Execution duration of functions.<br>+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| Function | Calls | Avg | P95 | Total | % Total |<br>+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| main | 1 | 1.56 ms | 1.56 ms | 1.56 ms | 100.00% |<br>+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| n_plus_one_before::list_comments | 1 | 104.29 µs | 104.32 µs | 104.29 µs | 6.67% |<br>+----------------------------------+-------+-----------+-----------+-----------+---------+
sql - SQL query execution time statistics.<br>Total calls: 143<br>+--------------------------------------------------------------+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| Query | Source | Calls | Avg | P95 | Total | % Total |<br>+--------------------------------------------------------------+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| CREATE TABLE posts (id INTEGER PRIMARY KEY, title TEXT NO... | - | 1 | 510.25 µs | 510.46 µs | 510.25 µs | 61.55% |<br>+--------------------------------------------------------------+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| INSERT INTO `comments` (`id`, `post_id`, `body`) VALUES (... | - | 100 | 1.65 µs | 1.71 µs | 165.29 µs | 19.94% |<br>+--------------------------------------------------------------+----------------------------------+-------+-----------+-----------+-----------+---------+<br>| SELECT `comments`.`id`, `comments`.`post_id`, `comments`.... | n_plus_one_before::list_comments | 20 | 3.42 µs | 3.21 µs | 68.45 µs | 8.26%...