Skip to content

Conversation

pepijnve
Copy link
Contributor

Which issue does this PR close?

None

Rationale for this change

More microbenchmarks make it easier to asses the performance impact of CaseExpr implementation changes.

What changes are included in this PR?

Add microbenchmarks for case expressions that are a bit more representative for real world queries.

Are these changes tested?

n/a

Are there any user-facing changes?

no

@github-actions github-actions bot added the physical-expr Changes to the physical-expr crates label Oct 16, 2025
Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @pepijnve -- I ran these benchmarks locally and it looks good

I also did a brief profile and it looks like it is measuring what we expect:

Screenshot 2025-10-16 at 1 48 07 PM


fn criterion_benchmark(c: &mut Criterion) {
// create input data
fn make_batch(row_count: usize, column_count: usize) -> RecordBatch {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth a comment saying that this column could is always 3 or more?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a description and assertion

));
let mut columns: Vec<ArrayRef> = vec![c1, c2, c3];
for _ in 3..column_count {
columns.push(Arc::new(Int32Array::from_value(0, row_count)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think it would be useful to use different values for the columns? Maybe since it is a benchmark (not correctness test) all zeros will be fine

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values themselves don't really matter for the benchmark. Maybe it's safer to not use identical values just to be sure that the array never gets REE encoded.

);

// No expression, when/then/else, column reference values
c.bench_function(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are nice labels:

Benchmarking case_when 8192x3: CASE WHEN c1 == 0 THEN 0 WHEN c1 == 1 THEN 1 ... WHEN c1 == n THEN n ELSE n + 1 EN...: Warming up for 3.0000 s


// Many when/then branches where all are effectively reachable
c.bench_function(format!("case_when {}x{}: CASE WHEN c1 == 0 THEN 0 WHEN c1 == 1 THEN 1 ... WHEN c1 == n THEN n ELSE n + 1 END", batch.num_rows(), batch.num_columns()).as_str(), |b| {
let when_thens = (0..batch.num_rows() as i32).map(|i| (make_x_cmp_y(&c1, Operator::Eq, i), lit(i))).collect();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is a lot of when_thens!

Copy link
Contributor Author

@pepijnve pepijnve Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally so. This is a torture test benchmark to really stress the code.

The first 'all reachable' one is really a worst case scenario test case. This is intended to be able to measure improvements in the processing that's being done in each loop iteration. Filtering, scattering, etc.

The second 'few reachable' one is intended to measure the short circuiting behaviour.

@alamb alamb added this pull request to the merge queue Oct 17, 2025
@alamb
Copy link
Contributor

alamb commented Oct 17, 2025

Thank you @pepijnve

Merged via the queue into apache:main with commit 765f2b9 Oct 17, 2025
32 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Oct 18, 2025
## Which issue does this PR close?

- Followup to #18097

## Rationale for this change

The last benchmark was incorrectly essentially indentical to the second
to last one. The actual predicate was using `=` instead of `<`.

## What changes are included in this PR?

- Adjust the operator in the case predicates to `<`
- Adds two additional benchmarks covering `case x when ...`

## Are these changes tested?

Verified with debugger.

## Are there any user-facing changes?

No
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

physical-expr Changes to the physical-expr crates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants