Skip to content

Commit 853eee0

Browse files
Add benchmark utility to profile peak memory usage (#16814)
* add benchmark utility to profile memory usage * get memory stats from mimalloc, not procfs * support more benchmarks * update benchmarks/README and refactor * fix sort-tpch output format & taplo format * add e2e test & comments * update description to major page fault --------- Co-authored-by: Yongting You <[email protected]>
1 parent 3dc3aaa commit 853eee0

File tree

13 files changed

+844
-265
lines changed

13 files changed

+844
-265
lines changed

Cargo.lock

Lines changed: 309 additions & 236 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmarks/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,21 @@ workspace = true
3333
ci = []
3434
default = ["mimalloc"]
3535
snmalloc = ["snmalloc-rs"]
36+
mimalloc_extended = ["libmimalloc-sys/extended"]
3637

3738
[dependencies]
3839
arrow = { workspace = true }
3940
datafusion = { workspace = true, default-features = true }
4041
datafusion-common = { workspace = true, default-features = true }
4142
env_logger = { workspace = true }
4243
futures = { workspace = true }
44+
libmimalloc-sys = { version = "0.1", optional = true }
4345
log = { workspace = true }
4446
mimalloc = { version = "0.1", optional = true, default-features = false }
4547
object_store = { workspace = true }
4648
parquet = { workspace = true, default-features = true }
4749
rand = { workspace = true }
50+
regex.workspace = true
4851
serde = { version = "1.0.219", features = ["derive"] }
4952
serde_json = { workspace = true }
5053
snmalloc-rs = { version = "0.3", optional = true }

benchmarks/README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ This will produce output like:
283283
└──────────────┴──────────────┴──────────────┴───────────────┘
284284
```
285285

286+
286287
# Benchmark Runner
287288

288289
The `dfbench` program contains subcommands to run the various
@@ -321,6 +322,66 @@ FLAGS:
321322
...
322323
```
323324

325+
# Profiling Memory Stats for each benchmark query
326+
The `mem_profile` program wraps benchmark execution to measure memory usage statistics, such as peak RSS. It runs each benchmark query in a separate subprocess, capturing the child process’s stdout to print structured output.
327+
328+
Subcommands supported by mem_profile are the subset of those in `dfbench`.
329+
Currently supported benchmarks include: Clickbench, H2o, Imdb, SortTpch, Tpch
330+
331+
Before running benchmarks, `mem_profile` automatically compiles the benchmark binary (`dfbench`) using `cargo build`. Note that the build profile used for `dfbench` is not tied to the profile used for running `mem_profile` itself. We can explicitly specify the desired build profile using the `--bench-profile` option (e.g. release-nonlto). By prebuilding the binary and running each query in a separate process, we can ensure accurate memory statistics.
332+
333+
Currently, `mem_profile` only supports `mimalloc` as the memory allocator, since it relies on `mimalloc`'s API to collect memory statistics.
334+
335+
Because it runs the compiled binary directly from the target directory, make sure your working directory is the top-level datafusion/ directory, where the target/ is also located.
336+
337+
The benchmark subcommand (e.g., `tpch`) and all following arguments are passed directly to `dfbench`. Be sure to specify `--bench-profile` before the benchmark subcommand.
338+
339+
Example:
340+
```shell
341+
datafusion$ cargo run --profile release-nonlto --bin mem_profile -- --bench-profile release-nonlto tpch --path benchmarks/data/tpch_sf1 --partitions 4 --format parquet
342+
```
343+
Example Output:
344+
```
345+
Query Time (ms) Peak RSS Peak Commit Major Page Faults
346+
----------------------------------------------------------------
347+
1 503.42 283.4 MB 3.0 GB 0
348+
2 431.09 240.7 MB 3.0 GB 0
349+
3 594.28 350.1 MB 3.0 GB 0
350+
4 468.90 462.4 MB 3.0 GB 0
351+
5 653.58 385.4 MB 3.0 GB 0
352+
6 296.79 247.3 MB 2.0 GB 0
353+
7 662.32 652.4 MB 3.0 GB 0
354+
8 702.48 396.0 MB 3.0 GB 0
355+
9 774.21 611.5 MB 3.0 GB 0
356+
10 733.62 397.9 MB 3.0 GB 0
357+
11 271.71 209.6 MB 3.0 GB 0
358+
12 512.60 212.5 MB 2.0 GB 0
359+
13 507.83 381.5 MB 2.0 GB 0
360+
14 420.89 313.5 MB 3.0 GB 0
361+
15 539.97 288.0 MB 2.0 GB 0
362+
16 370.91 229.8 MB 3.0 GB 0
363+
17 758.33 467.0 MB 2.0 GB 0
364+
18 1112.32 638.9 MB 3.0 GB 0
365+
19 712.72 280.9 MB 2.0 GB 0
366+
20 620.64 402.9 MB 2.9 GB 0
367+
21 971.63 388.9 MB 2.9 GB 0
368+
22 404.50 164.8 MB 2.0 GB 0
369+
```
370+
371+
## Reported Metrics
372+
When running benchmarks, `mem_profile` collects several memory-related statistics using the mimalloc API:
373+
374+
- Peak RSS (Resident Set Size):
375+
The maximum amount of physical memory used by the process.
376+
This is a process-level metric collected via OS-specific mechanisms and is not mimalloc-specific.
377+
378+
- Peak Commit:
379+
The peak amount of memory committed by the allocator (i.e., total virtual memory reserved).
380+
This is mimalloc-specific. It gives a more allocator-aware view of memory usage than RSS.
381+
382+
- Major Page Faults:
383+
The number of major page faults triggered during execution.
384+
This metric is obtained from the operating system and is not mimalloc-specific.
324385
# Writing a new benchmark
325386

326387
## Creating or downloading data outside of the benchmark

0 commit comments

Comments
 (0)