Skip to content

Wrap immutable plan parts into Arc (make creating ExecutionPlans less costly)#19893

Merged
alamb merged 1 commit intoapache:mainfrom
askalt:askalt/arc_immutable
Feb 4, 2026
Merged

Wrap immutable plan parts into Arc (make creating ExecutionPlans less costly)#19893
alamb merged 1 commit intoapache:mainfrom
askalt:askalt/arc_immutable

Conversation

@askalt
Copy link
Contributor

@askalt askalt commented Jan 20, 2026

Which issue does this PR close?

Rationale for this change

Improve performance of query planning and plan state re-set by making node clone cheap.

What changes are included in this PR?

  • Store projection as Option<Arc<[usize]>> instead of Option<Vec<usize>> in FilterExec, HashJoinExec, NestedLoopJoinExec.
  • Store exprs as Arc<[ProjectionExpr]> instead of Vec in ProjectionExprs.
  • Store arced aggregation, filter, group by expressions within AggregateExec.

@github-actions github-actions bot added physical-expr Changes to the physical-expr crates optimizer Optimizer rules core Core DataFusion crate common Related to common crate proto Related to proto crate physical-plan Changes to the physical-plan crate labels Jan 20, 2026
@askalt askalt force-pushed the askalt/arc_immutable branch from b9caf1d to bb97763 Compare January 20, 2026 08:17
@askalt
Copy link
Contributor Author

askalt commented Jan 20, 2026

run benchmark reset_plan_states

@alamb-ghbot
Copy link

🤖 Hi @askalt, thanks for the request (#19893 (comment)). scrape_comments.py only responds to whitelisted users. Allowed users: Dandandan, Omega359, adriangb, alamb, comphead, gabotechs, geoffreyclaude, klion26, rluvaton, xudong963, zhuqi-lucas.

@askalt
Copy link
Contributor Author

askalt commented Jan 20, 2026

@xudong963 could you please run benchmark reset_plan_states?

@xudong963
Copy link
Member

run benchmark reset_plan_states

@alamb-ghbot
Copy link

🤖 ./gh_compare_branch_bench.sh compare_branch_bench.sh Running
Linux aal-dev 6.14.0-1018-gcp #19~24.04.1-Ubuntu SMP Wed Sep 24 23:23:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing askalt/arc_immutable (bb97763) to d90d074 diff
BENCH_NAME=reset_plan_states
BENCH_COMMAND=cargo bench --features=parquet --bench reset_plan_states
BENCH_FILTER=
BENCH_BRANCH_NAME=askalt_arc_immutable
Results will be posted here when complete

@alamb-ghbot
Copy link

🤖: Benchmark completed

Details

group     askalt_arc_immutable                   main
-----     --------------------                   ----
query1    1.00     32.2±1.09ms        ? ?/sec    1.01     32.4±0.31ms        ? ?/sec
query2    1.00      9.2±0.08ms        ? ?/sec    1.03      9.5±0.11ms        ? ?/sec
query3    1.00     12.2±0.25ms        ? ?/sec    1.15     14.1±0.08ms        ? ?/sec

@askalt askalt force-pushed the askalt/arc_immutable branch 2 times, most recently from 70a396a to 3614687 Compare January 21, 2026 10:04
@github-actions github-actions bot added datasource Changes to the datasource crate and removed optimizer Optimizer rules core Core DataFusion crate common Related to common crate proto Related to proto crate labels Jan 21, 2026
@askalt askalt force-pushed the askalt/arc_immutable branch from 3614687 to bb97763 Compare January 21, 2026 10:08
@github-actions github-actions bot added optimizer Optimizer rules core Core DataFusion crate common Related to common crate proto Related to proto crate and removed datasource Changes to the datasource crate labels Jan 21, 2026
@askalt askalt force-pushed the askalt/arc_immutable branch from bb97763 to f2d829a Compare January 21, 2026 10:11
@github-actions github-actions bot added the datasource Changes to the datasource crate label Jan 26, 2026
@askalt askalt force-pushed the askalt/arc_immutable branch from 20b3042 to e6fed67 Compare January 26, 2026 20:45
@askalt
Copy link
Contributor Author

askalt commented Jan 26, 2026

I decided to simplify Statistics::project and project_schema signature and take an Option slice. Added a note to upgrading.md. Anyway, @crepererum thank you for the mentioned trick!

@askalt askalt force-pushed the askalt/arc_immutable branch 3 times, most recently from 1e27378 to 2c0746c Compare January 27, 2026 07:03
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.

I am sorry this is taking so long, but I a very worried about API churn and it takes me a non trivial amount of time to review the potential implications of this change

I have two major points:

  1. I really think it is important to not force downstream users to change how they call project_schema as it is a very common operation and there is no technical reason we can't keep their code the same (though it is harder in Datafusion). I made a PR to do so (and backout many of the changes currently required in this PR): askalt#5 as suggested by @crepererum
  2. As I mentioned previously OptionProjectionRef seems overly complicated to me to add to the public API -- and because the Option is wrapped, it means that the normal functions for Option (like match and .and_then, etc) don't work. I think it would be simpler, and follow the rest of the code more closely if it were Option<ProjectionRef> and the special projection application code is put into ProjectionRef

Thank you for your work on this @askalt

@askalt
Copy link
Contributor Author

askalt commented Jan 29, 2026

I am sorry this is taking so long, but I a very worried about API churn and it takes me a non trivial amount of time to review the potential implications of this change

I have two major points:

  1. I really think it is important to not force downstream users to change how they call project_schema as it is a very common operation and there is no technical reason we can't keep their code the same (though it is harder in Datafusion). I made a PR to do so (and backout many of the changes currently required in this PR): askalt#5 as suggested by @crepererum
  2. As I mentioned previously OptionProjectionRef seems overly complicated to me to add to the public API -- and because the Option is wrapped, it means that the normal functions for Option (like match and .and_then, etc) don't work. I think it would be simpler, and follow the rest of the code more closely if it were Option<ProjectionRef> and the special projection application code is put into ProjectionRef

Thank you for your work on this @askalt

Ok, I will do it.

@askalt askalt force-pushed the askalt/arc_immutable branch from 2c0746c to 6053a7c Compare February 3, 2026 20:08
@github-actions github-actions bot removed catalog Related to the catalog crate datasource Changes to the datasource crate labels Feb 3, 2026
@askalt askalt force-pushed the askalt/arc_immutable branch from 6053a7c to 5d11e60 Compare February 3, 2026 20:57
@github-actions github-actions bot removed the documentation Improvements or additions to documentation label Feb 3, 2026
@askalt
Copy link
Contributor Author

askalt commented Feb 3, 2026

I am sorry this is taking so long, but I a very worried about API churn and it takes me a non trivial amount of time to review the potential implications of this change

I have two major points:

  1. I really think it is important to not force downstream users to change how they call project_schema as it is a very common operation and there is no technical reason we can't keep their code the same (though it is harder in Datafusion). I made a PR to do so (and backout many of the changes currently required in this PR): askalt#5 as suggested by @crepererum
  2. As I mentioned previously OptionProjectionRef seems overly complicated to me to add to the public API -- and because the Option is wrapped, it means that the normal functions for Option (like match and .and_then, etc) don't work. I think it would be simpler, and follow the rest of the code more closely if it were Option<ProjectionRef> and the special projection application code is put into ProjectionRef

Thank you for your work on this @askalt

@alamb, done as suggested, please check

  1. No API changes in project_schema and stats project, take &impl AsRef<[usize>].
  2. Extract Option out from ProjectionRef. To achieve an ability to build plans from both Option<ProjectionRef> and Option<Vec<usize>> (to save existing API) -- HashJoinExecBuilder, NestedLoopJoinExecBuilder are added: they have two methods to be able to set projection from both vec and ref.

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.

Thank you @askalt - this looks really nice to me now. I think the code is faster and easier to work with 🏆 (HashJoinExecBuilder, NestedLoopJoinExecBuilder are especially nice)

I'll kick off a final benchmark run but I think this should be good to merge tomorrow

hash_join.null_aware,
)?)))
Ok(Some(Arc::new(
HashJoinExecBuilder::from(hash_join)
Copy link
Contributor

Choose a reason for hiding this comment

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

❤️

@@ -1370,9 +1377,9 @@ impl ExecutionPlan for AggregateExec {
) -> Result<Arc<dyn ExecutionPlan>> {
let mut me = AggregateExec::try_new_with_schema(
Copy link
Contributor

Choose a reason for hiding this comment

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

As a follow on PR, I think we can probably avoid a lot of redundant work here -- try_new_with_schema does many things, including re-compute plan properties

}
}

/// Helps to build [`HashJoinExec`].
Copy link
Contributor

Choose a reason for hiding this comment

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

This is very nice

@alamb
Copy link
Contributor

alamb commented Feb 3, 2026

run benchmark sql_planner

1 similar comment
@alamb
Copy link
Contributor

alamb commented Feb 3, 2026

run benchmark sql_planner

@alamb-ghbot
Copy link

🤖 ./gh_compare_branch_bench.sh compare_branch_bench.sh Running
Linux aal-dev 6.14.0-1018-gcp #19~24.04.1-Ubuntu SMP Wed Sep 24 23:23:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing askalt/arc_immutable (5d11e60) to a41f908 diff
BENCH_NAME=sql_planner
BENCH_COMMAND=cargo bench --features=parquet --bench sql_planner
BENCH_FILTER=
BENCH_BRANCH_NAME=askalt_arc_immutable
Results will be posted here when complete

@alamb-ghbot
Copy link

🤖: Benchmark completed

Details

group                                                 askalt_arc_immutable                   main
-----                                                 --------------------                   ----
logical_aggregate_with_join                           1.00    639.0±8.93µs        ? ?/sec    1.00    636.1±5.95µs        ? ?/sec
logical_select_all_from_1000                          1.07     11.4±0.25ms        ? ?/sec    1.00     10.6±0.09ms        ? ?/sec
logical_select_one_from_700                           1.00    412.7±3.54µs        ? ?/sec    1.02    419.3±3.62µs        ? ?/sec
logical_trivial_join_high_numbered_columns            1.00    372.8±3.99µs        ? ?/sec    1.01    377.1±9.20µs        ? ?/sec
logical_trivial_join_low_numbered_columns             1.00    360.2±8.10µs        ? ?/sec    1.01    362.9±9.47µs        ? ?/sec
physical_intersection                                 1.00  1594.8±19.66µs        ? ?/sec    1.00   1590.7±8.20µs        ? ?/sec
physical_join_consider_sort                           1.00      2.3±0.01ms        ? ?/sec    1.01      2.3±0.02ms        ? ?/sec
physical_join_distinct                                1.00    348.8±2.94µs        ? ?/sec    1.02    356.7±4.97µs        ? ?/sec
physical_many_self_joins                              1.00     12.5±0.08ms        ? ?/sec    1.01     12.7±0.28ms        ? ?/sec
physical_plan_clickbench_all                          1.00    199.6±2.83ms        ? ?/sec    1.01    200.9±1.66ms        ? ?/sec
physical_plan_clickbench_q1                           1.01      2.2±0.02ms        ? ?/sec    1.00      2.1±0.02ms        ? ?/sec
physical_plan_clickbench_q10                          1.01      3.7±0.04ms        ? ?/sec    1.00      3.6±0.04ms        ? ?/sec
physical_plan_clickbench_q11                          1.02      4.2±0.13ms        ? ?/sec    1.00      4.1±0.06ms        ? ?/sec
physical_plan_clickbench_q12                          1.01      4.3±0.07ms        ? ?/sec    1.00      4.2±0.04ms        ? ?/sec
physical_plan_clickbench_q13                          1.01      3.8±0.08ms        ? ?/sec    1.00      3.8±0.06ms        ? ?/sec
physical_plan_clickbench_q14                          1.00      4.2±0.08ms        ? ?/sec    1.00      4.2±0.04ms        ? ?/sec
physical_plan_clickbench_q15                          1.02      3.9±0.08ms        ? ?/sec    1.00      3.9±0.04ms        ? ?/sec
physical_plan_clickbench_q16                          1.01      3.7±0.05ms        ? ?/sec    1.00      3.7±0.10ms        ? ?/sec
physical_plan_clickbench_q17                          1.01      3.8±0.05ms        ? ?/sec    1.00      3.8±0.02ms        ? ?/sec
physical_plan_clickbench_q18                          1.00      2.7±0.03ms        ? ?/sec    1.00      2.7±0.02ms        ? ?/sec
physical_plan_clickbench_q19                          1.00      4.2±0.04ms        ? ?/sec    1.01      4.2±0.06ms        ? ?/sec
physical_plan_clickbench_q2                           1.02      2.8±0.05ms        ? ?/sec    1.00      2.8±0.04ms        ? ?/sec
physical_plan_clickbench_q20                          1.00      2.2±0.04ms        ? ?/sec    1.01      2.2±0.02ms        ? ?/sec
physical_plan_clickbench_q21                          1.00      2.8±0.06ms        ? ?/sec    1.00      2.8±0.02ms        ? ?/sec
physical_plan_clickbench_q22                          1.00      3.9±0.03ms        ? ?/sec    1.00      3.9±0.03ms        ? ?/sec
physical_plan_clickbench_q23                          1.00      4.2±0.04ms        ? ?/sec    1.00      4.2±0.03ms        ? ?/sec
physical_plan_clickbench_q24                          1.01      4.9±0.06ms        ? ?/sec    1.00      4.8±0.09ms        ? ?/sec
physical_plan_clickbench_q25                          1.00      3.5±0.05ms        ? ?/sec    1.00      3.5±0.03ms        ? ?/sec
physical_plan_clickbench_q26                          1.00      2.9±0.06ms        ? ?/sec    1.00      2.9±0.08ms        ? ?/sec
physical_plan_clickbench_q27                          1.00      3.5±0.04ms        ? ?/sec    1.01      3.5±0.03ms        ? ?/sec
physical_plan_clickbench_q28                          1.00      4.4±0.04ms        ? ?/sec    1.02      4.5±0.07ms        ? ?/sec
physical_plan_clickbench_q29                          1.00      4.7±0.05ms        ? ?/sec    1.01      4.7±0.10ms        ? ?/sec
physical_plan_clickbench_q3                           1.01      2.6±0.04ms        ? ?/sec    1.00      2.5±0.02ms        ? ?/sec
physical_plan_clickbench_q30                          1.00     15.6±0.25ms        ? ?/sec    1.00     15.6±0.47ms        ? ?/sec
physical_plan_clickbench_q31                          1.00      4.4±0.10ms        ? ?/sec    1.01      4.5±0.05ms        ? ?/sec
physical_plan_clickbench_q32                          1.00      4.4±0.07ms        ? ?/sec    1.00      4.4±0.03ms        ? ?/sec
physical_plan_clickbench_q33                          1.00      3.6±0.04ms        ? ?/sec    1.00      3.6±0.05ms        ? ?/sec
physical_plan_clickbench_q34                          1.00      3.2±0.03ms        ? ?/sec    1.02      3.3±0.03ms        ? ?/sec
physical_plan_clickbench_q35                          1.00      3.3±0.03ms        ? ?/sec    1.01      3.3±0.04ms        ? ?/sec
physical_plan_clickbench_q36                          1.00      4.2±0.06ms        ? ?/sec    1.01      4.2±0.06ms        ? ?/sec
physical_plan_clickbench_q37                          1.00      4.6±0.08ms        ? ?/sec    1.00      4.6±0.05ms        ? ?/sec
physical_plan_clickbench_q38                          1.00      4.6±0.05ms        ? ?/sec    1.00      4.6±0.07ms        ? ?/sec
physical_plan_clickbench_q39                          1.01      4.1±0.15ms        ? ?/sec    1.00      4.0±0.04ms        ? ?/sec
physical_plan_clickbench_q4                           1.00      2.2±0.02ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_clickbench_q40                          1.00      4.9±0.05ms        ? ?/sec    1.01      4.9±0.04ms        ? ?/sec
physical_plan_clickbench_q41                          1.00      4.3±0.05ms        ? ?/sec    1.00      4.2±0.05ms        ? ?/sec
physical_plan_clickbench_q42                          1.00      4.2±0.03ms        ? ?/sec    1.02      4.2±0.05ms        ? ?/sec
physical_plan_clickbench_q43                          1.00      4.5±0.07ms        ? ?/sec    1.01      4.5±0.09ms        ? ?/sec
physical_plan_clickbench_q44                          1.00      2.3±0.03ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
physical_plan_clickbench_q45                          1.00      2.3±0.02ms        ? ?/sec    1.02      2.3±0.04ms        ? ?/sec
physical_plan_clickbench_q46                          1.00      3.2±0.08ms        ? ?/sec    1.01      3.2±0.03ms        ? ?/sec
physical_plan_clickbench_q47                          1.00      4.7±0.04ms        ? ?/sec    1.01      4.7±0.03ms        ? ?/sec
physical_plan_clickbench_q48                          1.00      5.1±0.06ms        ? ?/sec    1.01      5.2±0.05ms        ? ?/sec
physical_plan_clickbench_q49                          1.00      5.4±0.07ms        ? ?/sec    1.02      5.5±0.10ms        ? ?/sec
physical_plan_clickbench_q5                           1.00      2.5±0.03ms        ? ?/sec    1.01      2.6±0.05ms        ? ?/sec
physical_plan_clickbench_q50                          1.00      4.1±0.09ms        ? ?/sec    1.00      4.1±0.09ms        ? ?/sec
physical_plan_clickbench_q51                          1.00      3.5±0.03ms        ? ?/sec    1.01      3.6±0.03ms        ? ?/sec
physical_plan_clickbench_q6                           1.01      2.6±0.05ms        ? ?/sec    1.00      2.5±0.02ms        ? ?/sec
physical_plan_clickbench_q7                           1.00      2.1±0.02ms        ? ?/sec    1.01      2.1±0.04ms        ? ?/sec
physical_plan_clickbench_q8                           1.00      3.5±0.11ms        ? ?/sec    1.00      3.4±0.02ms        ? ?/sec
physical_plan_clickbench_q9                           1.01      3.6±0.04ms        ? ?/sec    1.00      3.6±0.04ms        ? ?/sec
physical_plan_tpcds_all                               1.00  1911.0±11.23ms        ? ?/sec    1.01  1925.6±11.91ms        ? ?/sec
physical_plan_tpch_all                                1.00    126.6±1.39ms        ? ?/sec    1.00    127.0±1.06ms        ? ?/sec
physical_plan_tpch_q1                                 1.00      3.0±0.04ms        ? ?/sec    1.02      3.0±0.02ms        ? ?/sec
physical_plan_tpch_q10                                1.00      7.2±0.09ms        ? ?/sec    1.00      7.2±0.05ms        ? ?/sec
physical_plan_tpch_q11                                1.01      8.6±0.10ms        ? ?/sec    1.00      8.6±0.11ms        ? ?/sec
physical_plan_tpch_q12                                1.00      3.0±0.02ms        ? ?/sec    1.00      3.1±0.03ms        ? ?/sec
physical_plan_tpch_q13                                1.00      3.0±0.02ms        ? ?/sec    1.00      3.0±0.02ms        ? ?/sec
physical_plan_tpch_q14                                1.00      3.0±0.02ms        ? ?/sec    1.02      3.1±0.02ms        ? ?/sec
physical_plan_tpch_q16                                1.01      5.3±0.13ms        ? ?/sec    1.00      5.2±0.02ms        ? ?/sec
physical_plan_tpch_q17                                1.00      5.6±0.14ms        ? ?/sec    1.00      5.6±0.02ms        ? ?/sec
physical_plan_tpch_q18                                1.00      5.9±0.05ms        ? ?/sec    1.00      5.9±0.05ms        ? ?/sec
physical_plan_tpch_q19                                1.00      5.1±0.09ms        ? ?/sec    1.00      5.1±0.05ms        ? ?/sec
physical_plan_tpch_q2                                 1.00     12.3±0.23ms        ? ?/sec    1.00     12.4±0.12ms        ? ?/sec
physical_plan_tpch_q20                                1.00      8.0±0.09ms        ? ?/sec    1.01      8.1±0.07ms        ? ?/sec
physical_plan_tpch_q21                                1.00     10.1±0.18ms        ? ?/sec    1.01     10.2±0.22ms        ? ?/sec
physical_plan_tpch_q22                                1.00      6.4±0.05ms        ? ?/sec    1.00      6.4±0.15ms        ? ?/sec
physical_plan_tpch_q3                                 1.00      5.7±0.03ms        ? ?/sec    1.00      5.6±0.04ms        ? ?/sec
physical_plan_tpch_q4                                 1.00      3.0±0.03ms        ? ?/sec    1.00      3.0±0.02ms        ? ?/sec
physical_plan_tpch_q5                                 1.01      6.0±0.09ms        ? ?/sec    1.00      6.0±0.04ms        ? ?/sec
physical_plan_tpch_q6                                 1.01  1603.6±18.59µs        ? ?/sec    1.00  1594.6±11.44µs        ? ?/sec
physical_plan_tpch_q7                                 1.00      7.1±0.10ms        ? ?/sec    1.00      7.2±0.05ms        ? ?/sec
physical_plan_tpch_q8                                 1.00      9.3±0.06ms        ? ?/sec    1.02      9.4±0.08ms        ? ?/sec
physical_plan_tpch_q9                                 1.00      6.6±0.04ms        ? ?/sec    1.02      6.7±0.08ms        ? ?/sec
physical_select_aggregates_from_200                   1.00     17.4±0.14ms        ? ?/sec    1.00     17.3±0.17ms        ? ?/sec
physical_select_all_from_1000                         1.05     24.8±0.27ms        ? ?/sec    1.00     23.6±0.15ms        ? ?/sec
physical_select_one_from_700                          1.00  1320.3±15.76µs        ? ?/sec    1.02  1350.2±17.45µs        ? ?/sec
physical_sorted_union_order_by_10_int64               1.00     11.0±0.17ms        ? ?/sec    1.00     11.0±0.17ms        ? ?/sec
physical_sorted_union_order_by_10_uint64              1.00     29.7±0.52ms        ? ?/sec    1.00     29.6±0.50ms        ? ?/sec
physical_sorted_union_order_by_50_int64               1.00    195.6±2.04ms        ? ?/sec    1.01    197.3±2.20ms        ? ?/sec
physical_sorted_union_order_by_50_uint64              1.00  1077.4±10.21ms        ? ?/sec    1.01   1089.6±7.92ms        ? ?/sec
physical_theta_join_consider_sort                     1.00      2.6±0.02ms        ? ?/sec    1.01      2.7±0.02ms        ? ?/sec
physical_unnest_to_join                               1.01      3.1±0.01ms        ? ?/sec    1.00      3.0±0.03ms        ? ?/sec
physical_window_function_partition_by_12_on_values    1.00   1564.2±9.18µs        ? ?/sec    1.01  1577.5±13.71µs        ? ?/sec
physical_window_function_partition_by_30_on_values    1.00      2.9±0.04ms        ? ?/sec    1.00      2.9±0.03ms        ? ?/sec
physical_window_function_partition_by_4_on_values     1.00   1073.4±4.68µs        ? ?/sec    1.02  1091.3±18.24µs        ? ?/sec
physical_window_function_partition_by_7_on_values     1.00  1255.3±17.04µs        ? ?/sec    1.00   1256.7±6.10µs        ? ?/sec
physical_window_function_partition_by_8_on_values     1.00  1322.3±18.84µs        ? ?/sec    1.01  1331.4±22.12µs        ? ?/sec
with_param_values_many_columns                        1.03    596.4±5.04µs        ? ?/sec    1.00    577.7±4.64µs        ? ?/sec

@alamb-ghbot
Copy link

🤖 ./gh_compare_branch_bench.sh compare_branch_bench.sh Running
Linux aal-dev 6.14.0-1018-gcp #19~24.04.1-Ubuntu SMP Wed Sep 24 23:23:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing askalt/arc_immutable (5d11e60) to a41f908 diff
BENCH_NAME=sql_planner
BENCH_COMMAND=cargo bench --features=parquet --bench sql_planner
BENCH_FILTER=
BENCH_BRANCH_NAME=askalt_arc_immutable
Results will be posted here when complete

@alamb-ghbot
Copy link

🤖: Benchmark completed

Details

group                                                 askalt_arc_immutable                   main
-----                                                 --------------------                   ----
logical_aggregate_with_join                           1.00    636.9±7.89µs        ? ?/sec    1.01   641.2±10.50µs        ? ?/sec
logical_select_all_from_1000                          1.06     11.4±0.06ms        ? ?/sec    1.00     10.7±0.35ms        ? ?/sec
logical_select_one_from_700                           1.00    411.7±4.24µs        ? ?/sec    1.01    417.9±7.07µs        ? ?/sec
logical_trivial_join_high_numbered_columns            1.00    373.5±2.68µs        ? ?/sec    1.02   380.9±27.46µs        ? ?/sec
logical_trivial_join_low_numbered_columns             1.00    358.3±3.05µs        ? ?/sec    1.01    360.8±2.33µs        ? ?/sec
physical_intersection                                 1.01  1596.2±20.15µs        ? ?/sec    1.00  1583.1±16.63µs        ? ?/sec
physical_join_consider_sort                           1.00      2.3±0.02ms        ? ?/sec    1.01      2.3±0.01ms        ? ?/sec
physical_join_distinct                                1.00    348.0±2.85µs        ? ?/sec    1.02    353.4±6.61µs        ? ?/sec
physical_many_self_joins                              1.00     12.5±0.07ms        ? ?/sec    1.01     12.6±0.06ms        ? ?/sec
physical_plan_clickbench_all                          1.00    199.3±2.00ms        ? ?/sec    1.00    200.2±2.01ms        ? ?/sec
physical_plan_clickbench_q1                           1.01      2.1±0.02ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
physical_plan_clickbench_q10                          1.00      3.6±0.07ms        ? ?/sec    1.01      3.6±0.06ms        ? ?/sec
physical_plan_clickbench_q11                          1.00      4.1±0.02ms        ? ?/sec    1.01      4.1±0.06ms        ? ?/sec
physical_plan_clickbench_q12                          1.00      4.2±0.04ms        ? ?/sec    1.01      4.2±0.09ms        ? ?/sec
physical_plan_clickbench_q13                          1.00      3.7±0.03ms        ? ?/sec    1.01      3.7±0.02ms        ? ?/sec
physical_plan_clickbench_q14                          1.00      4.1±0.06ms        ? ?/sec    1.00      4.1±0.03ms        ? ?/sec
physical_plan_clickbench_q15                          1.00      3.8±0.06ms        ? ?/sec    1.00      3.8±0.03ms        ? ?/sec
physical_plan_clickbench_q16                          1.00      3.6±0.03ms        ? ?/sec    1.01      3.7±0.03ms        ? ?/sec
physical_plan_clickbench_q17                          1.00      3.7±0.03ms        ? ?/sec    1.01      3.8±0.09ms        ? ?/sec
physical_plan_clickbench_q18                          1.01      2.7±0.02ms        ? ?/sec    1.00      2.6±0.02ms        ? ?/sec
physical_plan_clickbench_q19                          1.00      4.2±0.08ms        ? ?/sec    1.01      4.2±0.08ms        ? ?/sec
physical_plan_clickbench_q2                           1.01      2.8±0.07ms        ? ?/sec    1.00      2.8±0.02ms        ? ?/sec
physical_plan_clickbench_q20                          1.00      2.2±0.01ms        ? ?/sec    1.00      2.2±0.06ms        ? ?/sec
physical_plan_clickbench_q21                          1.00      2.8±0.07ms        ? ?/sec    1.01      2.8±0.05ms        ? ?/sec
physical_plan_clickbench_q22                          1.00      3.9±0.02ms        ? ?/sec    1.00      3.9±0.05ms        ? ?/sec
physical_plan_clickbench_q23                          1.00      4.2±0.10ms        ? ?/sec    1.00      4.2±0.09ms        ? ?/sec
physical_plan_clickbench_q24                          1.00      4.8±0.10ms        ? ?/sec    1.00      4.8±0.11ms        ? ?/sec
physical_plan_clickbench_q25                          1.01      3.5±0.09ms        ? ?/sec    1.00      3.5±0.03ms        ? ?/sec
physical_plan_clickbench_q26                          1.02      2.9±0.05ms        ? ?/sec    1.00      2.9±0.02ms        ? ?/sec
physical_plan_clickbench_q27                          1.00      3.5±0.03ms        ? ?/sec    1.00      3.5±0.05ms        ? ?/sec
physical_plan_clickbench_q28                          1.00      4.4±0.04ms        ? ?/sec    1.00      4.4±0.04ms        ? ?/sec
physical_plan_clickbench_q29                          1.00      4.7±0.06ms        ? ?/sec    1.01      4.7±0.11ms        ? ?/sec
physical_plan_clickbench_q3                           1.00      2.5±0.01ms        ? ?/sec    1.01      2.5±0.03ms        ? ?/sec
physical_plan_clickbench_q30                          1.01     15.7±0.44ms        ? ?/sec    1.00     15.6±0.17ms        ? ?/sec
physical_plan_clickbench_q31                          1.01      4.5±0.10ms        ? ?/sec    1.00      4.4±0.04ms        ? ?/sec
physical_plan_clickbench_q32                          1.00      4.4±0.10ms        ? ?/sec    1.00      4.4±0.04ms        ? ?/sec
physical_plan_clickbench_q33                          1.00      3.6±0.03ms        ? ?/sec    1.00      3.6±0.03ms        ? ?/sec
physical_plan_clickbench_q34                          1.00      3.2±0.02ms        ? ?/sec    1.01      3.2±0.03ms        ? ?/sec
physical_plan_clickbench_q35                          1.00      3.3±0.03ms        ? ?/sec    1.00      3.3±0.02ms        ? ?/sec
physical_plan_clickbench_q36                          1.01      4.2±0.05ms        ? ?/sec    1.00      4.2±0.04ms        ? ?/sec
physical_plan_clickbench_q37                          1.00      4.6±0.09ms        ? ?/sec    1.00      4.6±0.05ms        ? ?/sec
physical_plan_clickbench_q38                          1.01      4.7±0.04ms        ? ?/sec    1.00      4.6±0.06ms        ? ?/sec
physical_plan_clickbench_q39                          1.00      4.1±0.06ms        ? ?/sec    1.00      4.0±0.04ms        ? ?/sec
physical_plan_clickbench_q4                           1.00      2.2±0.02ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_clickbench_q40                          1.00      4.9±0.08ms        ? ?/sec    1.00      4.9±0.09ms        ? ?/sec
physical_plan_clickbench_q41                          1.00      4.2±0.07ms        ? ?/sec    1.01      4.3±0.05ms        ? ?/sec
physical_plan_clickbench_q42                          1.00      4.2±0.06ms        ? ?/sec    1.01      4.2±0.04ms        ? ?/sec
physical_plan_clickbench_q43                          1.00      4.5±0.04ms        ? ?/sec    1.00      4.5±0.03ms        ? ?/sec
physical_plan_clickbench_q44                          1.00      2.3±0.03ms        ? ?/sec    1.00      2.3±0.02ms        ? ?/sec
physical_plan_clickbench_q45                          1.00      2.3±0.02ms        ? ?/sec    1.01      2.3±0.06ms        ? ?/sec
physical_plan_clickbench_q46                          1.00      3.2±0.05ms        ? ?/sec    1.00      3.2±0.10ms        ? ?/sec
physical_plan_clickbench_q47                          1.00      4.7±0.07ms        ? ?/sec    1.01      4.7±0.06ms        ? ?/sec
physical_plan_clickbench_q48                          1.00      5.1±0.08ms        ? ?/sec    1.00      5.1±0.06ms        ? ?/sec
physical_plan_clickbench_q49                          1.00      5.3±0.05ms        ? ?/sec    1.00      5.4±0.13ms        ? ?/sec
physical_plan_clickbench_q5                           1.00      2.5±0.01ms        ? ?/sec    1.00      2.5±0.01ms        ? ?/sec
physical_plan_clickbench_q50                          1.01      4.1±0.05ms        ? ?/sec    1.00      4.1±0.03ms        ? ?/sec
physical_plan_clickbench_q51                          1.01      3.5±0.04ms        ? ?/sec    1.00      3.5±0.05ms        ? ?/sec
physical_plan_clickbench_q6                           1.00      2.5±0.03ms        ? ?/sec    1.00      2.5±0.07ms        ? ?/sec
physical_plan_clickbench_q7                           1.00      2.1±0.03ms        ? ?/sec    1.00      2.1±0.03ms        ? ?/sec
physical_plan_clickbench_q8                           1.00      3.4±0.06ms        ? ?/sec    1.01      3.4±0.04ms        ? ?/sec
physical_plan_clickbench_q9                           1.00      3.6±0.06ms        ? ?/sec    1.01      3.6±0.01ms        ? ?/sec
physical_plan_tpcds_all                               1.00   1905.7±9.69ms        ? ?/sec    1.00  1911.9±10.74ms        ? ?/sec
physical_plan_tpch_all                                1.00    125.0±0.77ms        ? ?/sec    1.01    126.5±1.69ms        ? ?/sec
physical_plan_tpch_q1                                 1.00      3.0±0.04ms        ? ?/sec    1.01      3.0±0.02ms        ? ?/sec
physical_plan_tpch_q10                                1.00      7.2±0.05ms        ? ?/sec    1.00      7.2±0.07ms        ? ?/sec
physical_plan_tpch_q11                                1.00      8.5±0.06ms        ? ?/sec    1.01      8.5±0.12ms        ? ?/sec
physical_plan_tpch_q12                                1.01      3.1±0.06ms        ? ?/sec    1.00      3.1±0.03ms        ? ?/sec
physical_plan_tpch_q13                                1.01      3.0±0.03ms        ? ?/sec    1.00      3.0±0.03ms        ? ?/sec
physical_plan_tpch_q14                                1.00      3.0±0.10ms        ? ?/sec    1.02      3.1±0.05ms        ? ?/sec
physical_plan_tpch_q16                                1.00      5.2±0.04ms        ? ?/sec    1.00      5.2±0.07ms        ? ?/sec
physical_plan_tpch_q17                                1.00      5.5±0.02ms        ? ?/sec    1.01      5.6±0.04ms        ? ?/sec
physical_plan_tpch_q18                                1.00      5.9±0.03ms        ? ?/sec    1.00      5.9±0.04ms        ? ?/sec
physical_plan_tpch_q19                                1.00      5.0±0.05ms        ? ?/sec    1.00      5.0±0.03ms        ? ?/sec
physical_plan_tpch_q2                                 1.00     12.3±0.57ms        ? ?/sec    1.00     12.2±0.14ms        ? ?/sec
physical_plan_tpch_q20                                1.00      8.0±0.16ms        ? ?/sec    1.00      8.0±0.12ms        ? ?/sec
physical_plan_tpch_q21                                1.01     10.0±0.29ms        ? ?/sec    1.00     10.0±0.08ms        ? ?/sec
physical_plan_tpch_q22                                1.01      6.4±0.09ms        ? ?/sec    1.00      6.3±0.06ms        ? ?/sec
physical_plan_tpch_q3                                 1.00      5.6±0.04ms        ? ?/sec    1.00      5.5±0.04ms        ? ?/sec
physical_plan_tpch_q4                                 1.01      3.0±0.02ms        ? ?/sec    1.00      3.0±0.06ms        ? ?/sec
physical_plan_tpch_q5                                 1.00      5.9±0.06ms        ? ?/sec    1.00      5.9±0.05ms        ? ?/sec
physical_plan_tpch_q6                                 1.01  1595.6±14.81µs        ? ?/sec    1.00   1586.4±8.36µs        ? ?/sec
physical_plan_tpch_q7                                 1.00      7.1±0.05ms        ? ?/sec    1.01      7.2±0.05ms        ? ?/sec
physical_plan_tpch_q8                                 1.00      9.2±0.09ms        ? ?/sec    1.01      9.3±0.11ms        ? ?/sec
physical_plan_tpch_q9                                 1.00      6.6±0.14ms        ? ?/sec    1.01      6.7±0.20ms        ? ?/sec
physical_select_aggregates_from_200                   1.00     17.4±0.38ms        ? ?/sec    1.00     17.4±0.08ms        ? ?/sec
physical_select_all_from_1000                         1.04     24.8±0.19ms        ? ?/sec    1.00     23.9±0.30ms        ? ?/sec
physical_select_one_from_700                          1.00  1317.9±14.30µs        ? ?/sec    1.03  1351.3±26.08µs        ? ?/sec
physical_sorted_union_order_by_10_int64               1.00     10.9±0.19ms        ? ?/sec    1.01     11.0±0.09ms        ? ?/sec
physical_sorted_union_order_by_10_uint64              1.00     29.6±1.00ms        ? ?/sec    1.00     29.7±0.35ms        ? ?/sec
physical_sorted_union_order_by_50_int64               1.00    195.2±1.34ms        ? ?/sec    1.01    197.0±2.62ms        ? ?/sec
physical_sorted_union_order_by_50_uint64              1.00   1073.6±8.31ms        ? ?/sec    1.01   1087.3±8.17ms        ? ?/sec
physical_theta_join_consider_sort                     1.00      2.6±0.04ms        ? ?/sec    1.00      2.7±0.04ms        ? ?/sec
physical_unnest_to_join                               1.00      3.0±0.02ms        ? ?/sec    1.00      3.1±0.05ms        ? ?/sec
physical_window_function_partition_by_12_on_values    1.00  1569.4±32.75µs        ? ?/sec    1.00  1576.9±13.38µs        ? ?/sec
physical_window_function_partition_by_30_on_values    1.00      2.9±0.02ms        ? ?/sec    1.00      2.9±0.03ms        ? ?/sec
physical_window_function_partition_by_4_on_values     1.00  1084.3±23.50µs        ? ?/sec    1.00  1086.0±12.09µs        ? ?/sec
physical_window_function_partition_by_7_on_values     1.00   1254.1±8.64µs        ? ?/sec    1.01  1264.9±16.90µs        ? ?/sec
physical_window_function_partition_by_8_on_values     1.00   1315.4±6.65µs        ? ?/sec    1.00   1316.1±6.78µs        ? ?/sec
with_param_values_many_columns                        1.03    595.9±5.13µs        ? ?/sec    1.00    580.2±5.54µs        ? ?/sec

- Closes apache#19852

Improve performance of query planning and plan state re-set by making node clone cheap.

- Store projection as `Option<Arc<[usize]>>` instead of `Option<Vec<usize>>` in `FilterExec`,
  `HashJoinExec`, `NestedLoopJoinExec`.
- Store exprs as `Arc<[ProjectionExpr]>` instead of Vec in `ProjectionExprs`.
- Store arced aggregation, filter, group by expressions within `AggregateExec`.
@askalt askalt force-pushed the askalt/arc_immutable branch from 5d11e60 to a4bbb71 Compare February 4, 2026 06:34
@alamb alamb changed the title Wrap immutable plan parts into Arc Wrap immutable plan parts into Arc (make creating ExecutionPlans less costly) Feb 4, 2026
@alamb alamb added this pull request to the merge queue Feb 4, 2026
@alamb
Copy link
Contributor

alamb commented Feb 4, 2026

Thanks again @askalt and @martin-g

Merged via the queue into apache:main with commit d3ac7a3 Feb 4, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api change Changes the API exposed to users of the crate common Related to common crate core Core DataFusion crate optimizer Optimizer rules physical-expr Changes to the physical-expr crates physical-plan Changes to the physical-plan crate proto Related to proto crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrap more immutable plan parts into Arc

6 participants