Skip to content

Add stats estimation accuracy to benchmarks#556

Merged
gabotechs merged 1 commit into
mainfrom
gabrielmusat/stats-accuracy-benches
Jul 16, 2026
Merged

Add stats estimation accuracy to benchmarks#556
gabotechs merged 1 commit into
mainfrom
gabrielmusat/stats-accuracy-benches

Conversation

@gabotechs

@gabotechs gabotechs commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

This PR enhances the benchmarks by comparing estimated bytes vs actual bytes in network boundaries during dynamic planninng:

  • Compare sampled bytes with actual network-boundary output bytes using q-error.
  • Store it per iteration in local and remote benchmarks.
  • Report median q-error (QERR P50) in benchmark comparisons.

Preliminary step for #552.


Sample output:

=== Comparing tpch_sf10 results from branch 'stats-accuracy-benches' [prev] with 'stats-accuracy-benches' [new] ===
os:        macos
arch:      aarch64
cpu cores: 16
threads:   2 -> 2
workers:   8 -> 8
===================================================================================================================
tpch_sf10 q1: prev= 327 ms, new= 355 ms, diff=1.09 slower ✖
tpch_sf10 q2: prev= 271 ms, new= 278 ms, diff=1.03 slower ✖
tpch_sf10 q3: prev= 378 ms, new= 346 ms, diff=1.09 faster ✔
tpch_sf10 q4: prev= 132 ms, new= 129 ms, diff=1.02 faster ✔
tpch_sf10 q5: prev= 617 ms, new= 610 ms, diff=1.01 faster ✔
tpch_sf10 q6: prev= 115 ms, new= 109 ms, diff=1.06 faster ✔
tpch_sf10 q7: prev= 765 ms, new= 743 ms, diff=1.03 faster ✔
tpch_sf10 q8: prev= 781 ms, new= 889 ms, diff=1.14 slower ✖
tpch_sf10 q9: prev=1040 ms, new=1010 ms, diff=1.03 faster ✔
tpch_sf10 q10: prev= 448 ms, new= 455 ms, diff=1.02 slower ✖
tpch_sf10 q11: prev= 132 ms, new= 121 ms, diff=1.09 faster ✔
tpch_sf10 q12: prev= 200 ms, new= 205 ms, diff=1.02 slower ✖
tpch_sf10 q13: prev= 233 ms, new= 232 ms, diff=1.00 faster ✔
tpch_sf10 q14: prev= 158 ms, new= 171 ms, diff=1.08 slower ✖
tpch_sf10 q15: prev= 262 ms, new= 241 ms, diff=1.09 faster ✔
tpch_sf10 q16: prev=  92 ms, new=  94 ms, diff=1.02 slower ✖
tpch_sf10 q17: prev= 833 ms, new= 816 ms, diff=1.02 faster ✔
tpch_sf10 q18: prev= 917 ms, new= 946 ms, diff=1.03 slower ✖
tpch_sf10 q19: prev= 187 ms, new= 199 ms, diff=1.06 slower ✖
tpch_sf10 q20: prev= 422 ms, new= 420 ms, diff=1.00 faster ✔
tpch_sf10 q21: prev=1044 ms, new=1022 ms, diff=1.02 faster ✔
tpch_sf10 q22: prev= 101 ms, new= 103 ms, diff=1.02 slower ✖
   TOTAL: prev=9455 ms, new=9494 ms, diff=1.00 slower ✖
QERR P50: prev=n/a, new=19.47x

@gabotechs
gabotechs force-pushed the gabrielmusat/stats-accuracy-benches branch 5 times, most recently from ada6559 to 53809fb Compare July 16, 2026 08:16
Comment thread benchmarks/src/datasets/common.rs
Comment thread benchmarks/src/run.rs
#[structopt(long = "broadcast-joins")]
broadcast_joins: bool,

/// Collects metrics across network boundaries

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Now these two are always enabled. I don't think we want them disabled at any moment, as they are pretty stable now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unless tomorrow we want to follow Spark example and have a global AQE knob to turn it off, at that point we can avoid the overhead as there is no consumer. But we can probably do this later

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We would probably have the same effect by not inserting SampleExec nodes, so it's probably enough to do that tomorrow to disable AQE

@gabotechs
gabotechs force-pushed the gabrielmusat/stats-accuracy-benches branch from 53809fb to 050416b Compare July 16, 2026 08:21
@gabotechs
gabotechs marked this pull request as ready for review July 16, 2026 08:21
@gabotechs
gabotechs force-pushed the gabrielmusat/stats-accuracy-benches branch from 050416b to aac68dd Compare July 16, 2026 08:31

@asolimando asolimando left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, great work!

Comment thread benchmarks/src/stats.rs
let _ = plan.apply(|node| {
if let Some(boundary) = node.as_network_boundary()
&& let Stage::Local(input_stage) = boundary.input_stage()
&& let Some(sampled_bytes) = metric_total(&input_stage.metrics_set, "sampled_bytes")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think bytes will be the dominating factor in most cases, but we estimate row count too, I am OK to start with bytes only but if we see that this doesn't correlate with performance benchmarks, we might need to track row counts similarly.

Similarly for median, it's more stable than avg, and I think it's what we need to track, but we might need to add other percentile values possibly if we see that median is not enough.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think bytes will be the dominating factor in most cases, but we estimate row count too

Yeah, in fact, for future optimizations, rows will start being relevant, as that's what DF optimizer uses for several things.

As today we don't do those optimizations dynamically, and we just care about bytes for sizing the stages, bytes is the only thing that actually use.

When we start doing the other optimizations, I think we should start taking into account output rows as well.

@gabotechs
gabotechs force-pushed the gabrielmusat/stats-accuracy-benches branch 3 times, most recently from 71c347f to e7ee621 Compare July 16, 2026 09:30
Comment thread benchmarks/src/stats.rs Outdated
Ok(TreeNodeRecursion::Continue)
});

median(boundary_q_errors)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@asolimando I'm not sure if median is the best here... it has the chance of swallowing very bad estimations in cases there are enough straight-forward stages in the plan to even that out.

I'm thinking that avg might be a bit better. WDYT?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm getting some more meaningful metrics with a mean rather than median here, I'm going to go for it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I briefly touched upon this here and I agree that median, being robust to outliers, will "absord" degenerate cases that might result in individual queries to fail.

Being robust to outliers is a good property for this type of measures, avg would suffer from the opposite problem, it won't provide a clear signal for the "regular" case and conflate the two behaviors.

To track also outliers we need to complement median with P90 or P95, exactly as https://vldb.org/pvldb/vol9/p204-leis.pdf does (look at Table 1 page 4 for an example).

Median will already provide a good signal for most cases but as we move forward and refine the approach we will surely need more to avoid regressions for extreme cases.

If that's easy enough to add now, it would be safer, if you don't feel like adding it now, we can wait and see if better q-error median values positively correlates with improvements in benchmark results, otherwise we need extra signals.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤔 this is a good call... it's not trivial to do, but it's worth it, because I'm seeing that P50 is swallowing pretty wild overestimation, just because there's a few stages that are trivial to estimate (because 100% of the data was sampled for example)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Even if it's not super trivial, I'm going to go with P95 additionally, even if that will bloat a bit this PR.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done, P50 and P95 looking very good now, thanks for the suggestion!

@gabotechs
gabotechs force-pushed the gabrielmusat/stats-accuracy-benches branch 2 times, most recently from 82e6199 to 1610648 Compare July 16, 2026 10:47
@gabotechs
gabotechs force-pushed the gabrielmusat/stats-accuracy-benches branch from 1610648 to 94eec9c Compare July 16, 2026 11:00
@gabotechs
gabotechs merged commit 0f5cf3b into main Jul 16, 2026
31 checks passed
@gabotechs
gabotechs deleted the gabrielmusat/stats-accuracy-benches branch July 16, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants