An all-in-one profiler for Rust applications with real-time CPU and heap analysis (no external profilers, eBPF tools, or sidecar apps).
- CPU profiling - Timer-based sampling via perf events or the built-in sampler (no external profilers)
- Heap profiling - Custom allocator traces allocations, deallocations, and live memory
- Interactive TUI - Real-time charts and tables with vim-style navigation
- SQLite storage - Query profiles with SQL, export to JSON/CSV
- Symbol resolution - Full DWARF debug info support
[dependencies]
rsprof-trace = { version = "0.1", features = ["profiling"] }// One line enables CPU + heap profiling
rsprof_trace::profiler!();
fn main() {
// Your application code...
}Or customize the CPU sampling frequency:
rsprof_trace::profiler!(cpu = 199); // 199Hz instead of default 99HzIn your app, add a profiling profile:
[profile.profiling]
inherits = "release"
debug = trueThen build with frame pointers enabled:
RUSTFLAGS="-C force-frame-pointers=yes" cargo build --profile profiling# Start your application
./target/release/your_app &
# Attach the profiler
rsprof -p $(pgrep your_app)cargo install rsprofOr build from source:
git clone https://github.com/vibesrc/rsprof
cd rsprof
cargo install --path crates/rsprof# Profile by PID
rsprof -p 1234
# Profile by process name
rsprof -P my_app
# Save to specific file
rsprof -p 1234 -o profile.db
# Record for 30 seconds
rsprof -p 1234 -d 30s
# Quiet mode (no TUI, just record)
rsprof -p 1234 -q -d 10s# Interactive TUI viewer
rsprof view profile.db
# View most recent profile
rsprof view
# List available profiles
rsprof list# Top CPU consumers
rsprof top cpu profile.db
# Top memory consumers
rsprof top heap profile.db
# With options
rsprof top cpu profile.db -n 50 --threshold 1.0 --json
# Raw SQL queries
rsprof query profile.db "SELECT * FROM cpu_samples LIMIT 10"| Key | Action |
|---|---|
q / Esc |
Quit |
1 / 2 |
Switch to CPU / Memory view |
m |
Toggle view mode |
c / Enter |
Toggle chart visibility |
j / k |
Navigate table (down/up) |
h / l |
Pan chart (left/right) |
+ / - |
Zoom chart (in/out) |
Tab |
Switch focus (table/chart) |
p |
Pause/resume (live mode) |
The rsprof-trace crate supports conditional compilation:
# Profiling enabled (CPU + Heap)
rsprof-trace = { version = "0.1", features = ["profiling"] }
# Disabled (zero-cost passthrough)
rsprof-trace = { version = "0.1" }When no features are enabled, profiler!() expands to nothing and has zero overhead. This lets you keep the instrumentation in your code and toggle profiling at build time:
# Production build - no profiling
cargo build --release
# Profiling build
cargo build --release --features profilingMemory profiling tracks every allocation and deallocation in your application, letting you identify:
- Memory leaks - Allocations that are never freed
- High-churn allocations - Functions that allocate/free frequently
- Large allocations - Where your memory is going
- Live memory by call site - What's holding memory right now
| Metric | Description |
|---|---|
| Live bytes | Currently allocated memory (allocs - frees) |
| Total allocated | Cumulative bytes allocated |
| Total freed | Cumulative bytes freed |
| Alloc count | Number of allocation calls |
| Free count | Number of deallocation calls |
Press 2 or m in the TUI to switch to memory view. The table shows:
Live Trend Function Location
1.2MB ▂▃▅▇█▇▅ run_large_query src/main.rs:42
256KB ▁▁▂▂▃▃▄ create_session_data src/cache.rs:87
...
- Live - Current live bytes at this call site
- Trend - Sparkline showing memory over time
- Function - The allocation site (first user frame, not allocator internals)
Look for call sites where:
- Live bytes keep growing over time (upward sparkline trend)
- Alloc count >> Free count
# Query for potential leaks
rsprof query profile.db "
SELECT function, file, line,
total_alloc_bytes - total_free_bytes as leaked,
total_allocs - total_frees as leaked_count
FROM heap_samples
WHERE total_allocs > total_frees
ORDER BY leaked DESC
LIMIT 20
"- rsprof-trace writes profiling events to a shared memory ring buffer
- rsprof attaches to the process and reads events from shared memory
- Stack traces are captured using frame pointers for minimal overhead
- Data is stored in SQLite for persistence and queryability
- Linux (uses perf events and shared memory)
- Rust nightly (uses
let_chainsfeature) - Frame pointers enabled for accurate stack traces (use
RUSTFLAGS="-C force-frame-pointers=yes")
MIT

