Skip to content

Commit 6b9af2d

Browse files
committed
check benchmark
Signed-off-by: Connor Tsui <[email protected]>
1 parent 63931f0 commit 6b9af2d

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: Apache-2.0
3+
# SPDX-FileCopyrightText: Copyright the Vortex contributors
4+
5+
# Run query_bench --check with VORTEX_OPERATORS=true and =false, then diff the output.
6+
#
7+
# Usage:
8+
# ./diff_vortex_operators.sh statpopgen --scale-factor 1 --targets duckdb:vortex -q 7 --check
9+
10+
set -euo pipefail
11+
12+
RUST_LOG="${RUST_LOG:-error}"
13+
14+
echo "Running with VORTEX_OPERATORS=true..."
15+
output_true=$(VORTEX_OPERATORS=true RUST_LOG="$RUST_LOG" cargo run -p bench-vortex --bin query_bench -- "$@")
16+
17+
echo "Running with VORTEX_OPERATORS=false..."
18+
output_false=$(VORTEX_OPERATORS=false RUST_LOG="$RUST_LOG" cargo run -p bench-vortex --bin query_bench -- "$@")
19+
20+
echo ""
21+
echo "=== Diff (VORTEX_OPERATORS=true vs false) ==="
22+
diff <(echo "$output_true") <(echo "$output_false") || true

bench-vortex/src/benchmark_driver.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::fmt;
77
use std::path::PathBuf;
88

99
use anyhow::Result;
10+
use datafusion::arrow::util::pretty::pretty_format_batches;
1011
use indicatif::ProgressBar;
1112
use tracing::warn;
1213
use vortex::error::VortexExpect;
@@ -69,10 +70,16 @@ pub struct DriverConfig {
6970
pub skip_generate: bool,
7071
pub explain: bool,
7172
pub explain_analyze: bool,
73+
pub check: bool,
7274
}
7375

7476
/// Run a benchmark using the provided implementation and configuration
7577
pub fn run_benchmark<B: Benchmark>(benchmark: B, config: DriverConfig) -> Result<()> {
78+
// If check mode is enabled, run a single query and print results.
79+
if config.check {
80+
return run_check_query(benchmark, config);
81+
}
82+
7683
// If explain-analyze mode is enabled, run explain analyze
7784
if config.explain_analyze {
7885
return run_explain_query(benchmark, config, ExplainMode::Analyze);
@@ -425,3 +432,91 @@ fn run_explain_query<B: Benchmark>(
425432

426433
Ok(())
427434
}
435+
436+
/// Run a single query and print the results for correctness checking.
437+
fn run_check_query<B: Benchmark>(benchmark: B, config: DriverConfig) -> Result<()> {
438+
// Validate exactly one target.
439+
anyhow::ensure!(
440+
config.targets.len() == 1,
441+
"--check requires exactly 1 target, but {} were provided",
442+
config.targets.len()
443+
);
444+
445+
// Validate exactly one query is selected.
446+
let Some(ref queries) = config.queries else {
447+
anyhow::bail!("--check requires exactly 1 query to be specified via -q");
448+
};
449+
anyhow::ensure!(
450+
queries.len() == 1,
451+
"--check requires exactly 1 query, but {} were specified",
452+
queries.len()
453+
);
454+
455+
let target = &config.targets[0];
456+
457+
// Generate data (idempotent).
458+
if !config.skip_generate {
459+
benchmark.generate_data(target)?;
460+
}
461+
462+
let filtered_queries = filter_queries(
463+
benchmark.queries()?,
464+
config.queries.as_ref(),
465+
config.exclude_queries.as_ref(),
466+
);
467+
468+
let tokio_runtime = new_tokio_runtime(config.threads)?;
469+
470+
let engine_ctx = benchmark.setup_engine_context(
471+
target,
472+
config.disable_datafusion_cache,
473+
config.emit_plan,
474+
config.delete_duckdb_database,
475+
config.threads,
476+
)?;
477+
478+
tokio_runtime.block_on(benchmark.register_tables(&engine_ctx, target.format()))?;
479+
480+
for &(query_idx, ref query_string) in filtered_queries.iter() {
481+
println!("Query {}", query_idx);
482+
println!("SQL: {}\n", query_string);
483+
484+
match &engine_ctx {
485+
EngineCtx::DataFusion(ctx) => {
486+
match tokio_runtime.block_on(ctx.execute_query(query_string)) {
487+
Ok((batches, _plan)) => {
488+
let row_count: usize = batches.iter().map(|b| b.num_rows()).sum();
489+
match pretty_format_batches(&batches) {
490+
Ok(formatted) => println!("{}", formatted),
491+
Err(err) => eprintln!("Error formatting results: {}", err),
492+
}
493+
println!("\n({} rows)", row_count);
494+
}
495+
Err(err) => {
496+
eprintln!("Error running query {}: {}", query_idx, err);
497+
}
498+
}
499+
}
500+
EngineCtx::DuckDB(ctx) => match ctx.connection.query(query_string) {
501+
Ok(result) => {
502+
let mut row_count = 0u64;
503+
for chunk in result {
504+
row_count += chunk.len();
505+
match String::try_from(&chunk) {
506+
Ok(output) => println!("{}", output),
507+
Err(err) => {
508+
eprintln!("Error converting chunk to string: {}", err)
509+
}
510+
}
511+
}
512+
println!("\n({} rows)", row_count);
513+
}
514+
Err(err) => {
515+
eprintln!("Error running query {}: {}", query_idx, err);
516+
}
517+
},
518+
}
519+
}
520+
521+
Ok(())
522+
}

bench-vortex/src/bin/query_bench.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ struct CommonArgs {
113113

114114
#[arg(long, default_value_t = false)]
115115
explain_analyze: bool,
116+
117+
/// Run a single query once and print the results for correctness checking.
118+
/// Requires exactly 1 target and 1 query (via -q).
119+
#[arg(long, default_value_t = false)]
120+
check: bool,
116121
}
117122

118123
#[derive(Parser, Debug)]
@@ -322,6 +327,7 @@ fn run_clickbench(args: ClickBenchArgs) -> anyhow::Result<()> {
322327
skip_generate: args.common.skip_generate,
323328
explain: args.common.explain,
324329
explain_analyze: args.common.explain_analyze,
330+
check: args.common.check,
325331
};
326332

327333
// Determine data URL
@@ -354,6 +360,7 @@ fn run_tpch(args: TpcHArgs) -> anyhow::Result<()> {
354360
skip_generate: args.common.skip_generate,
355361
explain: args.common.explain,
356362
explain_analyze: args.common.explain_analyze,
363+
check: args.common.check,
357364
};
358365

359366
// Run benchmark using the trait system
@@ -387,6 +394,7 @@ fn run_tpcds(args: TpcDSArgs) -> anyhow::Result<()> {
387394
skip_generate: args.common.skip_generate,
388395
explain: args.common.explain,
389396
explain_analyze: args.common.explain_analyze,
397+
check: args.common.check,
390398
};
391399

392400
// Run benchmark using the trait system
@@ -422,6 +430,7 @@ fn run_statpopgen(args: StatPopGenArgs) -> anyhow::Result<()> {
422430
skip_generate: args.common.skip_generate,
423431
explain: args.common.explain,
424432
explain_analyze: args.common.explain_analyze,
433+
check: args.common.check,
425434
};
426435

427436
// Run benchmark using the trait system
@@ -451,6 +460,7 @@ fn run_fineweb(args: FinewebArgs) -> anyhow::Result<()> {
451460
skip_generate: args.common.skip_generate,
452461
explain: args.common.explain,
453462
explain_analyze: args.common.explain_analyze,
463+
check: args.common.check,
454464
};
455465

456466
run_benchmark(benchmark, config)
@@ -479,6 +489,7 @@ fn run_gharchive(args: GhArchiveArgs) -> anyhow::Result<()> {
479489
skip_generate: args.common.skip_generate,
480490
explain: args.common.explain,
481491
explain_analyze: args.common.explain_analyze,
492+
check: args.common.check,
482493
};
483494

484495
run_benchmark(benchmark, config)

0 commit comments

Comments
 (0)