Skip to content

Commit 691dd47

Browse files
authored
dev: Add benchmark for compilation profiles (#17754)
* Add benchmark for compilation profiles * add apache header * add apache header
1 parent 0fefbb1 commit 691dd47

File tree

4 files changed

+299
-27
lines changed

4 files changed

+299
-27
lines changed

Cargo.toml

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,56 @@ testcontainers-modules = { version = "0.12" }
179179
tokio = { version = "1.47", features = ["macros", "rt", "sync"] }
180180
url = "2.5.7"
181181

182+
[workspace.lints.clippy]
183+
# Detects large stack-allocated futures that may cause stack overflow crashes (see threshold in clippy.toml)
184+
large_futures = "warn"
185+
used_underscore_binding = "warn"
186+
or_fun_call = "warn"
187+
unnecessary_lazy_evaluations = "warn"
188+
uninlined_format_args = "warn"
189+
inefficient_to_string = "warn"
190+
191+
[workspace.lints.rust]
192+
unexpected_cfgs = { level = "warn", check-cfg = [
193+
'cfg(datafusion_coop, values("tokio", "tokio_fallback", "per_stream"))',
194+
"cfg(tarpaulin)",
195+
"cfg(tarpaulin_include)",
196+
] }
197+
unused_qualifications = "deny"
198+
199+
# --------------------
200+
# Compilation Profiles
201+
# --------------------
202+
# A Cargo profile is a preset for the compiler/linker knobs that trade off:
203+
# - Build time: how quickly code compiles and links
204+
# - Runtime performance: how fast the resulting binaries execute
205+
# - Binary size: how large the executables end up
206+
# - Debuggability: how much debug information is preserved for debugging and profiling
207+
#
208+
# Profiles available:
209+
# - dev: default debug build; fastest to compile, slowest to run, full debug info
210+
# for everyday development.
211+
# Run: cargo run
212+
# - release: optimized build; slowest to compile, fastest to run, smallest
213+
# binaries for public releases.
214+
# Run: cargo run --release
215+
# - release-nonlto: skips LTO, so it builds quicker while staying close to
216+
# release performance. It is useful when developing performance optimizations.
217+
# Run: cargo run --profile release-nonlto
218+
# - profiling: inherits release optimizations but retains debug info to support
219+
# profiling tools and flamegraphs.
220+
# Run: cargo run --profile profiling
221+
# - ci: derived from `dev` but disables incremental builds and strips dependency
222+
# symbols to keep CI artifacts small and reproducible.
223+
# Run: cargo run --profile ci
224+
#
225+
# If you want to optimize compilation, the `compile_profile` benchmark can be useful.
226+
# See `benchmarks/README.md` for more details.
182227
[profile.release]
183228
codegen-units = 1
184229
lto = true
185230
strip = true # Eliminate debug information to minimize binary size
186231

187-
# the release profile takes a long time to build so we can use this profile during development to save time
188-
# cargo build --profile release-nonlto
189232
[profile.release-nonlto]
190233
codegen-units = 16
191234
debug-assertions = false
@@ -202,33 +245,16 @@ debug = false
202245
inherits = "dev"
203246
incremental = false
204247

205-
# ci turns off debug info, etc. for dependencies to allow for smaller binaries making caching more effective
248+
# This rule applies to every package except workspace members (dependencies
249+
# such as `arrow` and `tokio`). It disables debug info and related features on
250+
# dependencies so their binaries stay smaller, improving cache reuse.
206251
[profile.ci.package."*"]
207252
debug = false
208253
debug-assertions = false
209254
strip = "debuginfo"
210255
incremental = false
211256

212-
# release inherited profile keeping debug information and symbols
213-
# for mem/cpu profiling
214257
[profile.profiling]
215258
inherits = "release"
216259
debug = true
217260
strip = false
218-
219-
[workspace.lints.clippy]
220-
# Detects large stack-allocated futures that may cause stack overflow crashes (see threshold in clippy.toml)
221-
large_futures = "warn"
222-
used_underscore_binding = "warn"
223-
or_fun_call = "warn"
224-
unnecessary_lazy_evaluations = "warn"
225-
uninlined_format_args = "warn"
226-
inefficient_to_string = "warn"
227-
228-
[workspace.lints.rust]
229-
unexpected_cfgs = { level = "warn", check-cfg = [
230-
'cfg(datafusion_coop, values("tokio", "tokio_fallback", "per_stream"))',
231-
"cfg(tarpaulin)",
232-
"cfg(tarpaulin_include)",
233-
] }
234-
unused_qualifications = "deny"

benchmarks/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,39 @@ To run for specific query, for example Q21
8787
./bench.sh run tpch10 21
8888
```
8989

90+
## Compile profile benchmark
91+
92+
Generate the data required for the compile profile helper (TPC-H SF=1):
93+
94+
```shell
95+
./bench.sh data compile_profile
96+
```
97+
98+
Run the benchmark across all default Cargo profiles (`dev`, `release`, `ci`, `release-nonlto`):
99+
100+
```shell
101+
./bench.sh run compile_profile
102+
```
103+
104+
Limit the run to a single profile:
105+
106+
```shell
107+
./bench.sh run compile_profile dev
108+
```
109+
110+
Or specify a subset of profiles:
111+
112+
```shell
113+
./bench.sh run compile_profile dev release
114+
```
115+
116+
You can also invoke the helper directly if you need to customise arguments further:
117+
118+
```shell
119+
./benchmarks/compile_profile.py --profiles dev release --data /path/to/tpch_sf1
120+
```
121+
122+
90123
## Benchmark with modified configurations
91124

92125
### Select join algorithm

benchmarks/bench.sh

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ imdb: Join Order Benchmark (JOB) using the IMDB dataset conver
125125
# Micro-Benchmarks (specific operators and features)
126126
cancellation: How long cancelling a query takes
127127
nlj: Benchmark for simple nested loop joins, testing various join scenarios
128+
compile_profile: Compile and execute TPC-H across selected Cargo profiles, reporting timing and binary size
128129
129130
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
130131
Supported Configuration (Environment Variables)
@@ -304,6 +305,9 @@ main() {
304305
# nlj uses range() function, no data generation needed
305306
echo "NLJ benchmark does not require data generation"
306307
;;
308+
compile_profile)
309+
data_tpch "1"
310+
;;
307311
*)
308312
echo "Error: unknown benchmark '$BENCHMARK' for data generation"
309313
usage
@@ -313,20 +317,32 @@ main() {
313317
run)
314318
# Parse positional parameters
315319
BENCHMARK=${ARG2:-"${BENCHMARK}"}
320+
EXTRA_ARGS=("${POSITIONAL_ARGS[@]:2}")
321+
PROFILE_ARGS=()
322+
QUERY=""
323+
QUERY_ARG=""
324+
if [ "$BENCHMARK" = "compile_profile" ]; then
325+
PROFILE_ARGS=("${EXTRA_ARGS[@]}")
326+
else
327+
QUERY=${EXTRA_ARGS[0]}
328+
if [ -n "$QUERY" ]; then
329+
QUERY_ARG="--query ${QUERY}"
330+
fi
331+
fi
316332
BRANCH_NAME=$(cd "${DATAFUSION_DIR}" && git rev-parse --abbrev-ref HEAD)
317333
BRANCH_NAME=${BRANCH_NAME//\//_} # mind blowing syntax to replace / with _
318334
RESULTS_NAME=${RESULTS_NAME:-"${BRANCH_NAME}"}
319335
RESULTS_DIR=${RESULTS_DIR:-"$SCRIPT_DIR/results/$RESULTS_NAME"}
320336

321-
# Optional query filter to run specific query
322-
QUERY=${ARG3}
323-
QUERY_ARG=$([ -n "$QUERY" ] && echo "--query ${QUERY}" || echo "")
324-
325337
echo "***************************"
326338
echo "DataFusion Benchmark Script"
327339
echo "COMMAND: ${COMMAND}"
328340
echo "BENCHMARK: ${BENCHMARK}"
329-
echo "QUERY: ${QUERY:-All}"
341+
if [ "$BENCHMARK" = "compile_profile" ]; then
342+
echo "PROFILES: ${PROFILE_ARGS[*]:-All}"
343+
else
344+
echo "QUERY: ${QUERY:-All}"
345+
fi
330346
echo "DATAFUSION_DIR: ${DATAFUSION_DIR}"
331347
echo "BRANCH_NAME: ${BRANCH_NAME}"
332348
echo "DATA_DIR: ${DATA_DIR}"
@@ -468,6 +484,9 @@ main() {
468484
nlj)
469485
run_nlj
470486
;;
487+
compile_profile)
488+
run_compile_profile "${PROFILE_ARGS[@]}"
489+
;;
471490
*)
472491
echo "Error: unknown benchmark '$BENCHMARK' for run"
473492
usage
@@ -593,6 +612,20 @@ run_tpch_mem() {
593612
debug_run $CARGO_COMMAND --bin tpch -- benchmark datafusion --iterations 5 --path "${TPCH_DIR}" --prefer_hash_join "${PREFER_HASH_JOIN}" -m --format parquet -o "${RESULTS_FILE}" ${QUERY_ARG}
594613
}
595614

615+
# Runs the compile profile benchmark helper
616+
run_compile_profile() {
617+
local profiles=("$@")
618+
local runner="${SCRIPT_DIR}/compile_profile.py"
619+
local data_path="${DATA_DIR}/tpch_sf1"
620+
621+
echo "Running compile profile benchmark..."
622+
local cmd=(python3 "${runner}" --data "${data_path}")
623+
if [ ${#profiles[@]} -gt 0 ]; then
624+
cmd+=(--profiles "${profiles[@]}")
625+
fi
626+
debug_run "${cmd[@]}"
627+
}
628+
596629
# Runs the cancellation benchmark
597630
run_cancellation() {
598631
RESULTS_FILE="${RESULTS_DIR}/cancellation.json"

0 commit comments

Comments
 (0)