Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
8a51e56
Substrate: multi-partition tasks + K-drain ShuffleWriter
avantgardnerio Jul 11, 2026
c8681ec
fix: size stage.partitions from the shuffle writer's child output_par…
avantgardnerio Jul 17, 2026
308f149
fix(task_builder): route each UnionExec parent partition to its child…
avantgardnerio Jul 17, 2026
fa54364
WIP: merge task_id / task_index into a single per-stage slot id
avantgardnerio Jul 17, 2026
ae53208
feat(scheduler): add ballista.scheduler.max_partitions_per_task cap
avantgardnerio Jul 17, 2026
8bd2e44
proto: reuse tag 3 for TaskId.global_output_partition_ids
avantgardnerio Jul 17, 2026
d4f6171
fix: preserve per-partition metrics under multi-partition tasks
avantgardnerio Jul 17, 2026
75be4d2
docs: explain multi-partition tasks, Spark comparison, and AQE compos…
avantgardnerio Jul 17, 2026
3854856
docs: prettier — use _emphasis_ not *emphasis*
avantgardnerio Jul 18, 2026
2b85079
docs: ASCII threading diagrams on ShuffleWriterExec and SortShuffleWr…
avantgardnerio Jul 18, 2026
b8f6ca8
fix: ShuffleWriter metrics — K buckets per task, keyed by operator-lo…
avantgardnerio Jul 19, 2026
c344920
fix: cross-product under-collect metrics against task slice, restorin…
avantgardnerio Jul 19, 2026
bc7a4ed
fix(config): default ballista.scheduler.max_partitions_per_task to 1 …
avantgardnerio Jul 19, 2026
39fa468
fix(scheduler): restrict PlaceholderRow/Empty leaves under fan-in splits
avantgardnerio Jul 19, 2026
8f592cc
test(scheduler): thread SessionConfig into aggregation-plan mock
avantgardnerio Jul 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,4 @@ CLAUDE.md
.worktrees/
# ignore insta captures
*-snap
.local/
41 changes: 37 additions & 4 deletions ballista/core/proto/ballista.proto
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,26 @@ message PartitionId {
uint32 partition_id = 4;
}

// Within-stage task identity (paired with job_id + stage_id on the parent
// MultiTaskDefinition). One task processes a slice of partitions, so
// `task_index` names the task within the stage; `global_output_partition_ids` gives
// the concrete global partition ids the task's restricted plan is
// covering. Writers use these to name shuffle files with global identity
// (via `create_shuffle_path`) so downstream reads have a stable, canonical
// address regardless of how the scheduler split the work.
message TaskId {
uint32 task_id = 1;
uint32 task_attempt_num = 2;
uint32 partition_id = 3;
Comment thread
avantgardnerio marked this conversation as resolved.
uint32 task_index = 3;
// Global partition ids covered by this task, in slice order. Position i in
// the restricted plan corresponds to `global_output_partition_ids[i]` globally.
repeated uint32 global_output_partition_ids = 4;
Comment thread
avantgardnerio marked this conversation as resolved.
Outdated
// Vcores this task consumed from the executor's budget at bind time.
// The executor uses this to size the task's memory pool proportionally
// (`pool = total_memory * vcores_consumed / total_vcores`), so a
// multi-partition task claiming N vcores gets N/total of the executor's
// memory budget rather than a single per-vcore share.
uint32 vcores_consumed = 5;
}

message PartitionStats {
Expand Down Expand Up @@ -530,7 +546,10 @@ message TaskStatus {
string job_id = 2;
uint32 stage_id = 3;
uint32 stage_attempt_num = 4;
uint32 partition_id = 5;
// Task index within the stage (was `partition_id` — under the
// multi-partition-task model one task processes a partition slice, not a
// single partition).
uint32 task_index = 5;
uint64 launch_time = 6;
uint64 start_exec_time = 7;
uint64 end_exec_time = 8;
Expand All @@ -549,17 +568,30 @@ message PollWorkParams {
repeated TaskStatus task_status = 3;
}

// Pull-based single-task dispatch. One task processes a slice of
// partitions; `task_index` names the task within the stage,
// `global_output_partition_ids` gives the concrete global partition ids it covers. The
// task's plan is scheduler-side shrink-restricted so its leaves report
// `slice.len()` partitions; the writer uses `global_output_partition_ids` to attach
// global identity to shuffle files (except in cases where the plan itself
// resets partitioning: the writer walks its child plan to detect
// SortPreservingMergeExec or RepartitionExec::Hash and picks the right
// global mapping).
message TaskDefinition {
uint32 task_id = 1;
uint32 task_attempt_num = 2;
string job_id = 3;
uint32 stage_id = 4;
uint32 stage_attempt_num = 5;
uint32 partition_id = 6;
uint32 task_index = 6;
Comment thread
avantgardnerio marked this conversation as resolved.
Outdated
bytes plan = 7;
string session_id = 9;
uint64 launch_time = 10;
repeated KeyValuePair props = 11;
// Global partition ids covered by this task, in slice order.
repeated uint32 global_output_partition_ids = 12;
Comment thread
andygrove marked this conversation as resolved.
// Vcores this task consumed at bind time — see TaskId.vcores_consumed.
uint32 vcores_consumed = 13;
}

// A set of tasks in the same stage
Expand Down Expand Up @@ -843,7 +875,8 @@ message RunningTaskInfo {
uint32 task_id = 1;
string job_id = 2;
uint32 stage_id = 3;
uint32 partition_id = 4;;
// Task slot within the stage (was `partition_id` — see TaskStatus).
uint32 task_index = 4;
}

service SchedulerGrpc {
Expand Down
1 change: 1 addition & 0 deletions ballista/core/src/execution_plans/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub use shuffle_reader::{CoalescePlan, PartitionGroup, ShuffleReaderExec};
pub use shuffle_reader::{stats_for_partition, stats_for_partitions};
pub use shuffle_writer::DEFAULT_SHUFFLE_CHANNEL_CAPACITY;
pub use shuffle_writer::ShuffleWriterExec;
pub use shuffle_writer::compute_global_output_partition_ids;
pub use shuffle_writer_trait::ShuffleWriter;
pub use sort_shuffle::SortShuffleWriterExec;
pub use unresolved_shuffle::UnresolvedShuffleExec;
Expand Down
5 changes: 4 additions & 1 deletion ballista/core/src/execution_plans/shuffle_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1772,7 +1772,10 @@ mod tests {
.map_err(|e| DataFusionError::Execution(format!("{e:?}")))
.unwrap();

assert_eq!(result.len(), 2);
// Writer's K=1 hash routes every row to partition 0. Its coordinator
// reads its full input slice (2 partitions × 2 batches = 4 batches),
// all routed to the single output file.
assert_eq!(result.len(), 4);
for b in result {
assert_eq!(b, create_test_batch())
}
Expand Down
Loading