Repository navigation
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
On my machine
OS: Fedora Linux 43 (KDE Plasma Desktop Edition) x86_64
Kernel: Linux 6.19.11-200.fc43.x86_64
CPU: AMD Ryzen AI 9 HX 370 (24) @ 5.16 GHz
GPU: AMD Radeon 890M Graphics [Integrated]
Memory: 11.96 GiB / 86.02 GiB (14%)
Swap: 0 B / 8.00 GiB (0%)
with updated rust:
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home: /home/bruce/.rustup
installed toolchains
--------------------
stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu
1.91.0-x86_64-unknown-linux-gnu
1.92.0-x86_64-unknown-linux-gnu
1.93.0-x86_64-unknown-linux-gnu
1.94.0-x86_64-unknown-linux-gnu (active)
active toolchain
----------------
name: 1.94.0-x86_64-unknown-linux-gnu
active because: overridden by '/home/bruce/dev/datafusion2/rust-toolchain.toml'
installed targets:
x86_64-unknown-linux-gnu
Running against main:
cd benchmarks;./bench.sh data tpch;./bench.sh run tpch 18 will hang
$ ./bench.sh run tpch 18
***************************
DataFusion Benchmark Script
COMMAND: run
BENCHMARK: tpch
QUERY: 18
DATAFUSION_DIR: /home/bruce/dev/datafusion2/benchmarks/..
BRANCH_NAME: HEAD
DATA_DIR: /home/bruce/dev/datafusion2/benchmarks/data
RESULTS_DIR: /home/bruce/dev/datafusion2/benchmarks/results/HEAD
CARGO_COMMAND: cargo run --release
PREFER_HASH_JOIN: true
SIMULATE_LATENCY: false
***************************
RESULTS_FILE: /home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json
Running tpch benchmark...
+ cargo run --release --bin dfbench -- tpch --iterations 5 --path /home/bruce/dev/datafusion2/benchmarks/data/tpch_sf1 --prefer_hash_join true --format parquet -o /home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json --query 18
Finished `release` profile [optimized] target(s) in 0.11s
Running `/home/bruce/dev/datafusion2/target/release/dfbench tpch --iterations 5 --path /home/bruce/dev/datafusion2/benchmarks/data/tpch_sf1 --prefer_hash_join true --format parquet -o /home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json --query 18`
Running benchmarks with the following options: RunOpt { query: Some(18), common: CommonOpt { iterations: 5, partitions: None, batch_size: None, mem_pool_type: "fair", memory_limit: None, sort_spill_reservation_bytes: None, debug: false, simulate_latency: false }, path: "/home/bruce/dev/datafusion2/benchmarks/data/tpch_sf1", file_format: "parquet", mem_table: false, output_path: Some("/home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json"), disable_statistics: false, prefer_hash_join: true, enable_piecewise_merge_join: false, sorted: false, hash_join_buffering_capacity: 0 }
git bisect points to this commit as the cause. Running the test at the commit just prior to that one succeeds. Running it at that commit fails.
If prefer_hash_join is disabled the query will run as expected:
PREFER_HASH_JOIN=false ./bench.sh run tpch 18
***************************
DataFusion Benchmark Script
COMMAND: run
BENCHMARK: tpch
QUERY: 18
DATAFUSION_DIR: /home/bruce/dev/datafusion2/benchmarks/..
BRANCH_NAME: HEAD
DATA_DIR: /home/bruce/dev/datafusion2/benchmarks/data
RESULTS_DIR: /home/bruce/dev/datafusion2/benchmarks/results/HEAD
CARGO_COMMAND: cargo run --release
PREFER_HASH_JOIN: false
SIMULATE_LATENCY: false
***************************
RESULTS_FILE: /home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json
Running tpch benchmark...
+ cargo run --release --bin dfbench -- tpch --iterations 5 --path /home/bruce/dev/datafusion2/benchmarks/data/tpch_sf1 --prefer_hash_join false --format parquet -o /home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json --query 18
Finished `release` profile [optimized] target(s) in 0.15s
Running `/home/bruce/dev/datafusion2/target/release/dfbench tpch --iterations 5 --path /home/bruce/dev/datafusion2/benchmarks/data/tpch_sf1 --prefer_hash_join false --format parquet -o /home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json --query 18`
Running benchmarks with the following options: RunOpt { query: Some(18), common: CommonOpt { iterations: 5, partitions: None, batch_size: None, mem_pool_type: "fair", memory_limit: None, sort_spill_reservation_bytes: None, debug: false, simulate_latency: false }, path: "/home/bruce/dev/datafusion2/benchmarks/data/tpch_sf1", file_format: "parquet", mem_table: false, output_path: Some("/home/bruce/dev/datafusion2/benchmarks/results/HEAD/tpch_sf1.json"), disable_statistics: false, prefer_hash_join: false, enable_piecewise_merge_join: false, sorted: false, hash_join_buffering_capacity: 0 }
Query 18 iteration 0 took 206.5 ms and returned 57 rows
Query 18 iteration 1 took 190.0 ms and returned 57 rows
Query 18 iteration 2 took 188.5 ms and returned 57 rows
Query 18 iteration 3 took 185.0 ms and returned 57 rows
Query 18 iteration 4 took 192.1 ms and returned 57 rows
Query 18 avg time: 192.42 ms
+ set +x
Done
To Reproduce
This seems to be machine/OS specific. I've been unable to reproduce on other machines.
Expected behavior
No response
Additional context
No response
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
adriangb commentedon Apr 14, 2026
@kosiew could you take a look?
maybe manually setting target partitions could help reproduce?
RatulDawar commentedon Apr 14, 2026
Hey @adriangb can I debug this ? Would also get some context around datafusion, really interested in this project.
adriangb commentedon Apr 14, 2026
Sure it can't help to get more help debugging 😃
RatulDawar commentedon Apr 14, 2026
take
adriangb commentedon Apr 14, 2026
Since you're new to this codebase I'd focus on reproducing the issue with a MRE that isn't OS/machine specific; don't worry about the fix too much for now.
Omega359 commentedon Apr 14, 2026
On my machine (12 cores, 24 with smt) running with
DATAFUSION_EXECUTION_TARGET_PARTITIONS=11works butDATAFUSION_EXECUTION_TARGET_PARTITIONS=12(or more) hangs. That is with prefer_hash_join=trueRatulDawar commentedon Apr 14, 2026
@Omega359 for me it's working always with prefer_hash_join=false and with prefer_hash_join=true it's failing for target_parititions > 12.
Also I see that a working instance with target partitions 4 gives a 400% CPU utiliztion vs a hanged instance gives 0% CPU utilization.
Probably suggesting that there a thread waiting/deadlock issue. Updating my findings further.
RatulDawar commentedon Apr 14, 2026
This can be minimally reproduced using this (essentially the same as the bench query)
RatulDawar commentedon Apr 14, 2026
@adriangb @Omega359 So I want able to find the issue here, the commit introduced a short circuit optimization where suppose if after the build process of the local partition there are zero rows, it doesn't need to run the probe state (as obviously there won't be any matches).
So this optimization basically marks the state from
build->completed.Problem arises when we are using dynamic filtering since dynamic filter is shared across partitions (since it's used to filter the probe side table) we use synchronization across parititons so that before passing the filter to probe side we have completed the filter collection from all the build side partitions.
Now when we significantly increase the target partitions count some partitions get zero rows allocated, which leads to the shot-circuit getting triggerd marking state of the empty partitions to completed.
Now these empty partitions never report the dynamic filters to the shared accumlator, which is waiting for the status to be reported by all the parititons. Leading to indefinite weight.
What I propose as a fix here is that for empty partitons we still report the filters to the shared accumlator and then mark it as completed. This would stop this indefinite weight situation.
If you guys are aligned I will raise a PR with this fix.
TL;DR:
The short-circuit optimization skips probe execution for empty partitions, but those partitions never report their dynamic filters. Since the shared accumulator waits for all partitions, this causes an indefinite wait. Fix: even empty partitions should report (empty) filters before marking themselves as completed.
adriangb commentedon Apr 14, 2026
That makes complete sense to me, great investigation @RatulDawar ! Do you want to work on the fix itself?
RatulDawar commentedon Apr 14, 2026
Yes, would love to ! Sharing the fix
RatulDawar commentedon Apr 14, 2026
@adriangb added the fix, can you please check ?
fix: remove barrier from SharedBuildAccumulator to resolve Q18 deadlock
test: add regression tests for SharedBuildAccumulator non-blocking co…
test: drop scan-level row-count assertions in dynamic filter pushdown…
fix: remove barrier from SharedBuildAccumulator to resolve Q18 deadlock
test: add regression tests for SharedBuildAccumulator non-blocking co…
adriangb commentedon Apr 16, 2026
I think I found another way to address this problem: #21666
It looks like the issue was a tokio task structuring issue (the task that reports results to the barrier was getting dropped/cancelled).
If you think about it this makes sense: theoretically there is no reason if a build side partition has no data it can't report as empty to the barrier and everything continues happily. So really #21068 just exposed an existing issue.
Handle canceled partitioned hash join dynamic filters lazily (apache#…