Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
5cdf7d5
copy paste aggregates as is to aggregates_blocked
rluvaton Aug 31, 2026
cc0e79a
update imports and make it compile
rluvaton Aug 31, 2026
5979c90
add steps
rluvaton Aug 31, 2026
16e3848
use existing structs from aggregate to avoid full duplication
rluvaton Aug 31, 2026
1a2e531
rename `AggregateExec` in blocked to `BlockedAggregateExec`
rluvaton Aug 31, 2026
f0f7b8d
update `AggregateExec::try_new` to return the `BlockedAggregateExec` …
rluvaton Aug 31, 2026
672ebb5
add fallback to BlockedAggregateExec so unsupported logic will be for…
rluvaton Aug 31, 2026
41b926c
Rename `GroupValues` to `BlockedGroupValues` and `GroupColumn` to `Bl…
rluvaton Aug 31, 2026
358d618
Add `BlockedIndex` and `BlockedEmitTo`
rluvaton Aug 31, 2026
464f8fe
Change in group indices to be stored internally as `BlocksIndex` and …
rluvaton Aug 31, 2026
e5d3895
Remove all `BlockedGroupValues` impl and replace with adapter
rluvaton Aug 31, 2026
1e9c6d1
Add `batch_size` to `BlockedGroupValues` for later emit change
rluvaton Aug 31, 2026
2ae5d2c
fallback to non blocked in `grouped_hash_stream` and removed duplicat…
rluvaton Sep 1, 2026
6970f8c
add blocked emit to
rluvaton Sep 1, 2026
a605809
changed intern to get BlocksIndex and not usize
rluvaton Sep 1, 2026
e6cdab2
create blocked groups accumulator
rluvaton Sep 1, 2026
d6a5479
remove print
rluvaton Sep 2, 2026
50796d5
fix compile for tests
rluvaton Sep 2, 2026
f76ba2a
add group indices to ordering
rluvaton Sep 2, 2026
22e0f32
Merge branch 'main' into add-blocks-impl-from-scratch
rluvaton Sep 2, 2026
9082071
fix emit too much
rluvaton Sep 2, 2026
0c67d68
add blocked group by boolean
rluvaton Sep 2, 2026
923ee62
add `state_preserving` to blocked group accumulator adapter
rluvaton Sep 2, 2026
0aeb359
add `evaluate_preserving` to blocked group accumulator adapter
rluvaton Sep 2, 2026
7fb5b7a
fix compile for BlockedGroupsSelection
rluvaton Sep 2, 2026
f511677
impl blocked group accumulator for sum
rluvaton Sep 2, 2026
11216d2
fix group by boolean
rluvaton Sep 2, 2026
ee5f265
add support for blocked min max
rluvaton Sep 2, 2026
98e7c1a
add more blocked helpers and tests
rluvaton Sep 3, 2026
e34750f
re-export and fix clippy
rluvaton Sep 3, 2026
292bde1
support blocked group accumulator in count
rluvaton Sep 3, 2026
10bf417
support blocked group accumulator in count distinct
rluvaton Sep 3, 2026
bc12f1e
support blocked min max bytes - add heap allocated custom bytes
rluvaton Sep 3, 2026
f05b37e
add support for blocked avg
rluvaton Sep 3, 2026
f7321e0
add support for percentile and median
rluvaton Sep 3, 2026
d884f4d
add support for group by single primitive column
rluvaton Sep 3, 2026
89e615f
add support for group by single bytes column
rluvaton Sep 3, 2026
d9d288b
impl bytes view
rluvaton Sep 3, 2026
ec2a018
impl multi group by with boolean column support
rluvaton Sep 3, 2026
f6e9ffe
impl multi group by with primitive column support
rluvaton Sep 3, 2026
9b64a45
fix byte view map
rluvaton Sep 3, 2026
4b685db
impl multi group by with bytes column support
rluvaton Sep 3, 2026
5711b81
impl multi group by with bytes view column support
rluvaton Sep 3, 2026
dc4c359
switch to BlockedAggregateExec in the rest of the code and fail on Ag…
rluvaton Sep 6, 2026
4499859
lint, format and fix build in test
rluvaton Sep 6, 2026
d3f9bae
support blocked group accumulator for correlation since h2o group by …
rluvaton Sep 6, 2026
4336407
fix wrong argument
rluvaton Sep 6, 2026
c0ea780
update aggregate stream with the current non blocked updated impl
rluvaton Sep 6, 2026
8f48bb7
Merge branch 'main' into add-blocks-impl-from-scratch
rluvaton Sep 6, 2026
f921483
change blocks index into packed u64, lets see the perf
rluvaton Sep 6, 2026
b3846dc
use blocked in view map
rluvaton Sep 6, 2026
e678670
remove resolved todo
rluvaton Sep 6, 2026
1a44055
let claude update `CopyItemBlockedVecBuilder` to use mmap so the data…
rluvaton Sep 6, 2026
5870a0d
Revert "change blocks index into packed u64, lets see the perf"
rluvaton Sep 6, 2026
a25342b
let claude update blocked boolean + nulls builder to use mmap, and in…
rluvaton Sep 6, 2026
e0d7a96
Revert "let claude update blocked boolean + nulls builder to use mmap…
rluvaton Sep 6, 2026
0074517
let claude increase mmap address space so we don't need to reallocate…
rluvaton Sep 6, 2026
10864ee
change to flat indexes
rluvaton Sep 6, 2026
e20af72
add idea about into iter on group values
rluvaton Sep 7, 2026
9396a63
implement dedicated take all rather than using take block in a loop f…
rluvaton Sep 7, 2026
4d3c197
build null once
rluvaton Sep 7, 2026
4b720d7
fix not all blocks for empty blocks
rluvaton Sep 7, 2026
38c8d88
let claude improve perf a little
rluvaton Sep 7, 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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions datafusion/common/src/utils/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

//! [`VecAllocExt`] to help tracking of memory allocations

use std::collections::VecDeque;
use hashbrown::hash_table::HashTable;
use std::mem::size_of;

Expand Down Expand Up @@ -111,6 +112,41 @@ impl<T> VecAllocExt for Vec<T> {
}
}

/// Extension trait for [`Vec`] to account for allocations.
pub trait VecDequeAllocExt {
/// Return the amount of memory allocated by this VecDeque to store elements
/// (`size_of<T> * capacity`).
///
/// Note this calculation is not recursive, and does not include any heap
/// allocations contained within the Vec's elements. Does not include the
/// size of `self`
///
/// # Example:
/// ```
/// # use datafusion_common::utils::proxy::VecDequeAllocExt;
/// let mut vec = VecDeque::new();
/// // Push data into the vec and the accounting will be updated to reflect
/// // memory allocation
/// vec.push_back(1);
/// assert_eq!(vec.allocated_size(), 16); // space for 4 u32s
/// vec.push_back(1);
/// assert_eq!(vec.allocated_size(), 16); // no new allocation needed
///
/// // push more data into the vec
/// for _ in 0..10 {
/// vec.push_back(1);
/// }
/// assert_eq!(vec.allocated_size(), 64); // space for 64 now
/// ```
fn allocated_size(&self) -> usize;
}

impl<T> VecDequeAllocExt for VecDeque<T> {
fn allocated_size(&self) -> usize {
size_of::<T>() * self.capacity()
}
}

/// Extension trait for hash browns [`HashTable`] to account for allocations.
pub trait HashTableAllocExt {
/// Item type.
Expand Down
5 changes: 3 additions & 2 deletions datafusion/core/src/physical_planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4576,7 +4576,7 @@ mod tests {

let execution_plan = plan(&logical_plan).await?;
let final_hash_agg = execution_plan
.downcast_ref::<AggregateExec>()
.downcast_ref::<BlockedAggregateExec>()
.expect("hash aggregate");
assert_eq!(
"sum(aggregate_test_100.c2)",
Expand All @@ -4603,7 +4603,7 @@ mod tests {

let execution_plan = plan(&logical_plan).await?;
let final_hash_agg = execution_plan
.downcast_ref::<AggregateExec>()
.downcast_ref::<BlockedAggregateExec>()
.expect("hash aggregate");
assert_eq!(
"sum(aggregate_test_100.c3)",
Expand Down Expand Up @@ -5610,6 +5610,7 @@ digraph {
use crate::catalog::TableProvider;
use datafusion_catalog::Session;
use datafusion_expr::TableType;
use datafusion_physical_plan::aggregates_blocked::BlockedAggregateExec;

/// A TableProvider that returns schemas for logical planning vs physical planning.
/// Used to test schema mismatch error messages.
Expand Down
5 changes: 4 additions & 1 deletion datafusion/core/tests/fuzz_cases/aggregate_fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,10 @@ async fn verify_ordered_aggregate(frame: &DataFrame, expected_sort: bool) {
type Node = Arc<dyn ExecutionPlan>;

fn f_down(&mut self, node: &'n Self::Node) -> Result<TreeNodeRecursion> {
if let Some(exec) = node.downcast_ref::<AggregateExec>() {
if node.downcast_ref::<AggregateExec>().is_some() {
return plan_err!("should not get AggregateExec, should be migrated to BlockedAggregateExec");
}
if let Some(exec) = node.downcast_ref::<BlockedAggregateExec>() {
if self.expected_sort {
assert!(matches!(
exec.input_order_mode(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use datafusion_physical_plan::ExecutionPlan;
use datafusion_physical_plan::aggregates::AggregateExec;
use datafusion_physical_plan::aggregates::AggregateMode;
use datafusion_physical_plan::aggregates::PhysicalGroupBy;
use datafusion_physical_plan::aggregates_blocked::BlockedAggregateExec;
use datafusion_physical_plan::coalesce_partitions::CoalescePartitionsExec;
use datafusion_physical_plan::common;
use datafusion_physical_plan::displayable;
Expand All @@ -74,7 +75,7 @@ fn mock_data() -> Result<Arc<DataSourceExec>> {

/// Checks that the count optimization was applied and we still get the right result
async fn assert_count_optim_success(
plan: AggregateExec,
plan: BlockedAggregateExec,
agg: TestAggregate,
) -> Result<()> {
let task_ctx = Arc::new(TaskContext::default());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use datafusion_physical_plan::{
collect, displayable,
limit::{GlobalLimitExec, LocalLimitExec},
};
use datafusion_physical_plan::aggregates_blocked::BlockedAggregateExec;

async fn run_plan_and_format(plan: Arc<dyn ExecutionPlan>) -> Result<String> {
let cfg = SessionConfig::new().with_target_partitions(1);
Expand Down Expand Up @@ -133,7 +134,12 @@ async fn limited_distinct_aggregate_stream_respects_soft_limit() -> Result<()> {
plan: &Arc<dyn ExecutionPlan>,
metrics: &mut Vec<AggregateRuntimeMetric>,
) {
if let Some(agg) = plan.downcast_ref::<AggregateExec>() {
assert!(
plan.downcast_ref::<AggregateExec>().is_none(),
"should not get AggregateExec, should be migrated to BlockedAggregateExec"
);

if let Some(agg) = plan.downcast_ref::<BlockedAggregateExec>() {
let output_rows = agg
.metrics()
.and_then(|metrics| metrics.aggregate_by_name().output_rows())
Expand Down
1 change: 1 addition & 0 deletions datafusion/core/tests/sql/explain_analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ async fn explain_analyze_baseline_metrics() {

plan.is::<sorts::sort::SortExec>()
|| plan.is::<physical_plan::aggregates::AggregateExec>()
|| plan.is::<physical_plan::aggregates_blocked::BlockedAggregateExec>()
|| plan.is::<physical_plan::filter::FilterExec>()
|| plan.is::<physical_plan::limit::LocalLimitExec>()
|| plan.is::<physical_plan::projection::ProjectionExec>()
Expand Down
1 change: 1 addition & 0 deletions datafusion/expr-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ arrow = { workspace = true }
datafusion-common = { workspace = true }
indexmap = { workspace = true }
itertools = { workspace = true }
libc = "0.2.185"

[dev-dependencies]
insta = { workspace = true }
Expand Down
Loading
Loading