Skip to content

Commit a71c19f

Browse files
committed
Merge branch 'xuanwo/asof-physical' into xuanwo/asof-logical
2 parents a15b693 + 339d785 commit a71c19f

1 file changed

Lines changed: 88 additions & 2 deletions

File tree

datafusion/physical-plan/src/joins/asof_join.rs

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use arrow::compute::{SortOptions, interleave};
6262
use arrow::datatypes::{Schema, SchemaRef};
6363
use datafusion_common::config::ConfigOptions;
6464
use datafusion_common::stats::Precision;
65+
use datafusion_common::utils::memory::RecordBatchMemoryCounter;
6566
use datafusion_common::utils::{
6667
compare_rows, get_row_at_idx, normalize_float_zero_scalar,
6768
};
@@ -93,7 +94,6 @@ use crate::metrics::{
9394
BaselineMetrics, Count, ExecutionPlanMetricsSet, Gauge, MetricBuilder,
9495
MetricCategory, MetricsSet, RecordOutput, Time,
9596
};
96-
use crate::spill::get_record_batch_memory_size;
9797
use crate::statistics::{ChildStats, StatisticsArgs};
9898
use crate::stream::RecordBatchStreamAdapter;
9999
use crate::{
@@ -609,9 +609,10 @@ async fn collect_right_input(
609609
metrics: AsOfJoinMetrics,
610610
) -> Result<BroadcastRightInput> {
611611
let schema = input.schema();
612+
let mut memory_counter = RecordBatchMemoryCounter::new();
612613
let batches = input
613614
.try_fold(Vec::new(), |mut batches, batch| {
614-
let batch_size = get_record_batch_memory_size(&batch);
615+
let batch_size = memory_counter.count_batch(&batch);
615616
futures::future::ready(reservation.try_grow(batch_size).map(|_| {
616617
metrics.build_mem_used.add(batch_size);
617618
metrics.build_input_batches.add(1);
@@ -1070,6 +1071,7 @@ mod tests {
10701071
};
10711072
use arrow::datatypes::{DataType, Field, Int8Type};
10721073
use datafusion_execution::config::SessionConfig;
1074+
use datafusion_execution::runtime_env::RuntimeEnvBuilder;
10731075
use datafusion_expr::ColumnarValue;
10741076
use datafusion_physical_expr_common::metrics::MetricValue;
10751077
use datafusion_physical_expr_common::physical_expr::PhysicalExpr;
@@ -1401,6 +1403,90 @@ mod tests {
14011403
Ok(())
14021404
}
14031405

1406+
#[tokio::test]
1407+
async fn shared_right_buffers_are_reserved_once() -> Result<()> {
1408+
let left_schema = Arc::new(Schema::new(vec![
1409+
Field::new("key", DataType::Utf8, false),
1410+
Field::new("ts", DataType::Int64, false),
1411+
Field::new("id", DataType::Int32, false),
1412+
]));
1413+
let left = TestMemoryExec::try_new_exec(
1414+
&[vec![make_batch(
1415+
&left_schema,
1416+
vec![Some("A")],
1417+
vec![Some(4095)],
1418+
vec![0],
1419+
)?]],
1420+
Arc::clone(&left_schema),
1421+
None,
1422+
)?;
1423+
1424+
let right_schema = Arc::new(Schema::new(vec![
1425+
Field::new("key", DataType::Utf8, false),
1426+
Field::new("ts", DataType::Int64, false),
1427+
Field::new("price", DataType::Int32, false),
1428+
]));
1429+
let row_count = 4096;
1430+
let parent = make_batch(
1431+
&right_schema,
1432+
vec![Some("A"); row_count],
1433+
(0..row_count).map(|value| Some(value as i64)).collect(),
1434+
(0..row_count as i32).collect(),
1435+
)?;
1436+
let mut memory_counter = RecordBatchMemoryCounter::new();
1437+
let retained_size = memory_counter.count_batch(&parent);
1438+
let right_batches = (0..16)
1439+
.map(|index| parent.slice(index * 256, 256))
1440+
.collect();
1441+
let right = TestMemoryExec::try_new_exec(
1442+
&[right_batches],
1443+
Arc::clone(&right_schema),
1444+
None,
1445+
)?;
1446+
1447+
let exec = Arc::new(AsOfJoinExec::try_new(
1448+
left,
1449+
right,
1450+
vec![(
1451+
Arc::new(PhysicalColumn::new("key", 0)),
1452+
Arc::new(PhysicalColumn::new("key", 0)),
1453+
)],
1454+
AsOfMatchExpr::new(
1455+
Arc::new(PhysicalColumn::new("ts", 1)),
1456+
Operator::GtEq,
1457+
Arc::new(PhysicalColumn::new("ts", 1)),
1458+
),
1459+
vec![2],
1460+
)?);
1461+
let runtime = RuntimeEnvBuilder::new()
1462+
.with_memory_limit(retained_size, 1.0)
1463+
.build_arc()?;
1464+
let context = Arc::new(TaskContext::default().with_runtime(runtime));
1465+
1466+
let batches = collect(Arc::clone(&exec) as _, context).await?;
1467+
let prices = batches
1468+
.iter()
1469+
.flat_map(|batch| {
1470+
batch
1471+
.column(3)
1472+
.as_any()
1473+
.downcast_ref::<Int32Array>()
1474+
.unwrap()
1475+
.iter()
1476+
})
1477+
.collect::<Vec<_>>();
1478+
assert_eq!(prices, vec![Some(4095)]);
1479+
1480+
let metrics = exec.metrics().expect("ASOF metrics must be present");
1481+
assert_eq!(
1482+
metrics
1483+
.sum_by_name("build_mem_used")
1484+
.map(|value| value.as_usize()),
1485+
Some(retained_size)
1486+
);
1487+
Ok(())
1488+
}
1489+
14041490
#[tokio::test]
14051491
async fn preserves_dictionary_outputs_across_large_flush() -> Result<()> {
14061492
let dictionary_type =

0 commit comments

Comments
 (0)