Expression optimisation rules don't introduce irreducible children - #9625
Expression optimisation rules don't introduce irreducible children#9625robert3005 wants to merge 1 commit into
Conversation
Merging this PR will improve performance by 22.86%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | mul_u64_nonnull_neon |
21 µs | 15.2 µs | +38.21% |
| ⚡ | WallTime | arrow_checked_add_u32_avx512[16384] |
21.3 µs | 17.6 µs | +21.17% |
| ⚡ | WallTime | mul_i64_nonnull_neon |
20.1 µs | 17.1 µs | +17.23% |
| ⚡ | WallTime | multiply_shapes_neon[(16384, PerRowPerRow)] |
20 µs | 17.3 µs | +16.06% |
Tip
Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.
Comparing rk/expridempotent (8789c70) with develop (33c52ab)
Footnotes
-
106 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
-
4 benchmarks were run, but are now archived. If they were deleted in another branch, consider rebasing to remove them from the report. Instead if they were added back, click here to restore them. ↩
Polar Signals Profiling ResultsLatest Run
Powered by Polar Signals Cloud |
Benchmarks: String Encoding 📖Commits: PR vortex / vortex-file-compressed / ms (0.996x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / % (1.000x ➖, 0↑ 0↓)
|
Benchmarks: PolarSignals Profiling 📖Commits: PR datafusion / vortex-file-compressed / ns (0.964x ➖, 1↑ 0↓)
No file size changes detected. |
Benchmarks: FineWeb NVMe 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.999x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.969x ➖, 1↑ 0↓)
datafusion / parquet / ns (1.010x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.037x ➖, 0↑ 2↓)
duckdb / vortex-compact / ns (0.968x ➖, 2↑ 0↓)
duckdb / parquet / ns (1.003x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: TPC-H SF=1 on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.999x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.009x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.985x ➖, 4↑ 0↓)
duckdb / vortex-file-compressed / ns (0.996x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.002x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.002x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: Clickbench Sorted on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.024x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.971x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.983x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.010x ➖, 1↑ 2↓)
duckdb / vortex-compact / ns (0.987x ➖, 1↑ 0↓)
duckdb / parquet / ns (0.991x ➖, 1↑ 0↓)
File Size Changes (200 files changed, +0.1% overall, 109↑ 91↓)
Totals:
|
Benchmarks: FineWeb S3 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.024x ➖, 0↑ 1↓)
datafusion / vortex-compact / ns (1.011x ➖, 0↑ 1↓)
datafusion / parquet / ns (0.966x ➖, 0↑ 1↓)
duckdb / vortex-file-compressed / ns (0.913x ➖, 1↑ 0↓)
duckdb / vortex-compact / ns (0.954x ➖, 0↑ 0↓)
duckdb / parquet / ns (0.908x ➖, 2↑ 1↓)
|
Benchmarks: Appian on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-compact / ns (1.004x ➖, 0↑ 0↓)
datafusion / parquet / ns (1.001x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.004x ➖, 0↑ 0↓)
duckdb / parquet / ns (0.995x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: Statistical and Population Genetics 📖Commits: PR How to read Verdict and Engines
duckdb / vortex-file-compressed / ns (0.996x ➖, 1↑ 0↓)
duckdb / vortex-compact / ns (1.012x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.006x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: TPC-DS SF=1 on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.999x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.001x ➖, 1↑ 0↓)
datafusion / parquet / ns (0.997x ➖, 0↑ 1↓)
duckdb / vortex-file-compressed / ns (0.991x ➖, 4↑ 2↓)
duckdb / vortex-compact / ns (1.000x ➖, 4↑ 3↓)
duckdb / parquet / ns (0.998x ➖, 4↑ 7↓)
No file size changes detected. |
Benchmarks: TPC-H SF=10 on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.989x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.990x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.997x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.009x ➖, 0↑ 1↓)
duckdb / vortex-compact / ns (0.996x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.005x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: Clickbench on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.998x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.000x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.998x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.004x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.002x ➖, 1↑ 1↓)
duckdb / parquet / ns (0.998x ➖, 1↑ 0↓)
No file size changes detected. |
Benchmarks: TPC-H SF=1 on S3 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.956x ➖, 1↑ 2↓)
datafusion / vortex-compact / ns (1.020x ➖, 0↑ 2↓)
datafusion / parquet / ns (1.007x ➖, 1↑ 1↓)
duckdb / vortex-file-compressed / ns (0.834x ➖, 2↑ 0↓)
duckdb / vortex-compact / ns (0.966x ➖, 0↑ 0↓)
duckdb / parquet / ns (0.949x ➖, 0↑ 0↓)
|
Benchmarks: Random Access 📖Commits: PR How to read Verdict and Engines
random-access / vortex-file-compressed / ns (1.011x ➖, 0↑ 1↓)
random-access / parquet / ns (1.000x ➖, 0↑ 0↓)
random-access / lance / ns (0.995x ➖, 1↑ 0↓)
|
Benchmarks: TPC-H SF=10 on S3 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-compact / ns (0.843x ➖, 5↑ 0↓)
datafusion / parquet / ns (0.836x ➖, 5↑ 0↓)
duckdb / vortex-compact / ns (0.912x ➖, 0↑ 1↓)
duckdb / parquet / ns (0.895x ➖, 0↑ 0↓)
|
Benchmarks: Compression 📖Commits: PR vortex / vortex-file-compressed / ns (0.972x ➖, 1↑ 0↓)
vortex / vortex-file-compressed / bytes (1.000x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / ratio (0.979x ➖, 1↑ 0↓)
vortex / parquet / ns (1.003x ➖, 0↑ 0↓)
vortex / parquet / bytes (1.000x ➖, 0↑ 0↓)
|
`Select::simplify` and `Merge::reduce` rewrite a struct expression into a `pack` that reads each field out of the rule's own child. Both wrote that read as a `get_item` node. When the child is itself a `pack`, that `get_item` is redundant, but the optimizer never removes it: `try_optimize_recursive_inner` visits children before their parent, so the children a parent rule introduces are never visited at all. `optimize_recursive` was therefore not a fixed point. A `select` over a `merge` of packs left behind one full copy of the child `pack` per selected field, and a second `optimize_recursive` call returned a different expression than the first. Read the field out of the child `pack` in the rules themselves, so their output needs no further pass. `Merge` shares `GetItem::project_node`, which falls back to a `get_item` node for a non-`pack` child. `Select` takes the pack children directly: its existing guard rules out the validity intersection that is the only way a field read can change a field dtype, so no mask node is needed. Signed-off-by: Robert Kruszewski <github@robertk.io>
27d7642 to
8789c70
Compare
Expression::optimize_recursive might need to reoptimise children after root
replacement. Keep looping in optimize_recursive until there are no changes
Signed-off-by: Robert Kruszewski github@robertk.io