forked from
atscan.net/plcbundle-rs
High-performance implementation of plcbundle written in Rust
1# Memory Profiling with `dhat`
2
3This project integrates the [`dhat`](https://docs.rs/dhat/latest/dhat/) heap profiler to analyze memory allocations across CLI commands. It works on macOS/Linux/Windows and writes a JSON profile you can open in DHAT’s HTML viewer.
4
5## Overview
6
7- Uses `dhat` as the global allocator to track allocations.
8- Starts the profiler at process startup and stops on exit.
9- Saves a profile file `dhat-heap.json` in the current working directory.
10- Best used in release mode with line-level debug info for clear backtraces.
11
12## Prerequisites
13
14- Rust toolchain installed.
15- This repository already wires `dhat`:
16 - Global allocator and profiler start: `src/cli/mod.rs:6-8`, `src/cli/mod.rs:154-155`
17 - Feature flag and release debug info: `Cargo.toml:76-79`, `Cargo.toml:82-84`
18
19## Enable Profiling
20
21Build and run with the profiling feature enabled:
22
23```bash
24cargo build --release --features dhat-heap
25cargo run --release --features dhat-heap -- <COMMAND> [ARGS]
26```
27
28Examples:
29
30```bash
31# Show repository status (quiet run)
32cargo run --release --features dhat-heap -- status --quiet
33
34# List bundles
35cargo run --release --features dhat-heap -- ls
36```
37
38Notes:
39
40- Use release builds (`--release`) for realistic performance and readable backtraces.
41- Avoid commands that immediately exit (`--help`, `--version`) if you want a profile; they may not exercise useful code paths.
42
43## Output
44
45After the command finishes, `dhat` prints a summary to stderr and writes `dhat-heap.json` in the current directory. For example:
46
47```
48dhat: Total: 433,983 bytes in 1,186 blocks
49dhat: At t-gmax: 314,288 bytes in 986 blocks
50dhat: At t-end: 806 bytes in 7 blocks
51dhat: The data has been saved to dhat-heap.json, and is viewable with dhat/dh_view.html
52```
53
54## Viewing the Profile
55
56Open DHAT’s viewer (`dh_view.html`) and load `dhat-heap.json`:
57
58- Option 1: Clone the viewer
59 - `git clone https://github.com/nnethercote/dhat-rs`
60 - Open `dhat-rs/dhat/dh_view.html` in your browser
61 - Use the “Load” button to select `dhat-heap.json`
62
63- Option 2: Use the copy from crate docs
64 - Refer to `dhat` crate documentation for viewer location and usage: https://docs.rs/dhat/latest/dhat/
65
66The viewer provides allocation hot spots, call stacks, counts, sizes, and lifetimes.
67
68## Customization
69
70If you need to customize the output file name or backtrace trimming, switch from `new_heap()` to the builder:
71
72```rust
73// Replace the default initialization in main with:
74let _profiler = dhat::Profiler::builder()
75 .file_name(format!("heap-{}.json", std::process::id()))
76 .trim_backtraces(Some(16))
77 .build();
78```
79
80Backtrace trimming defaults to a small depth to keep profiles readable and fast. Increase the frame count if you need deeper stacks, noting this increases overhead and file size.
81
82## Disabling Profiling
83
84- Omit the feature flag: run without `--features dhat-heap`.
85- The instrumentation is guarded by `#[cfg(feature = "dhat-heap")]`, so the binary runs with the normal allocator when the feature is disabled.
86
87## Tips
88
89- Profile realistic workloads (e.g., `sync`, `verify`, `server`) to see meaningful allocation behavior.
90- Consider ignoring generated profiles if you don’t want them in version control:
91 - Add `dhat-*.json` to `.gitignore`.
92- `dhat` adds overhead; keep it off for normal runs.
93
94## References
95
96- Crate docs: https://docs.rs/dhat/latest/dhat/
97- Profiler builder: https://docs.rs/dhat/latest/dhat/struct.ProfilerBuilder.html
98- Repository integration points:
99 - Global allocator: `src/cli/mod.rs:6-8`
100 - Profiler start: `src/cli/mod.rs:154-155`
101 - Feature and release profile: `Cargo.toml:76-79`, `Cargo.toml:82-84`