This is an automated email from the ASF dual-hosted git repository.

agrove pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-comet.git


The following commit(s) were added to refs/heads/main by this push:
     new 5af85f6a perf: add metrics to CopyExec and ScanExec (#778)
5af85f6a is described below

commit 5af85f6a8a434558eea00fc2773002897100af13
Author: Andy Grove <[email protected]>
AuthorDate: Mon Aug 5 17:08:54 2024 -0600

    perf: add metrics to CopyExec and ScanExec (#778)
---
 native/core/src/execution/jni_api.rs        |  3 +--
 native/core/src/execution/operators/copy.rs | 32 +++++++++++++++++++++----
 native/core/src/execution/operators/scan.rs | 36 ++++++++++++++++++++++++-----
 3 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/native/core/src/execution/jni_api.rs 
b/native/core/src/execution/jni_api.rs
index e4b13878..285d63e9 100644
--- a/native/core/src/execution/jni_api.rs
+++ b/native/core/src/execution/jni_api.rs
@@ -363,8 +363,7 @@ pub unsafe extern "system" fn 
Java_org_apache_comet_Native_executePlan(
                     if exec_context.debug_native {
                         if let Some(plan) = &exec_context.root_op {
                             let formatted_plan_str =
-                                
DisplayableExecutionPlan::with_full_metrics(plan.as_ref())
-                                    .indent(true);
+                                
DisplayableExecutionPlan::with_metrics(plan.as_ref()).indent(true);
                             info!("Comet native query plan with metrics:\n 
{formatted_plan_str:}");
                         }
                     }
diff --git a/native/core/src/execution/operators/copy.rs 
b/native/core/src/execution/operators/copy.rs
index 68c91aaf..b5b1491e 100644
--- a/native/core/src/execution/operators/copy.rs
+++ b/native/core/src/execution/operators/copy.rs
@@ -27,6 +27,7 @@ use futures::{Stream, StreamExt};
 use arrow_array::{ArrayRef, RecordBatch, RecordBatchOptions};
 use arrow_schema::{DataType, Field, FieldRef, Schema, SchemaRef};
 
+use datafusion::physical_plan::metrics::{BaselineMetrics, 
ExecutionPlanMetricsSet, MetricsSet};
 use datafusion::{execution::TaskContext, physical_expr::*, physical_plan::*};
 use datafusion_common::{arrow_datafusion_err, DataFusionError, Result as 
DataFusionResult};
 
@@ -42,6 +43,7 @@ pub struct CopyExec {
     input: Arc<dyn ExecutionPlan>,
     schema: SchemaRef,
     cache: PlanProperties,
+    metrics: ExecutionPlanMetricsSet,
 }
 
 impl CopyExec {
@@ -70,6 +72,7 @@ impl CopyExec {
             input,
             schema,
             cache,
+            metrics: ExecutionPlanMetricsSet::default(),
         }
     }
 }
@@ -107,6 +110,7 @@ impl ExecutionPlan for CopyExec {
             input: new_input,
             schema: self.schema.clone(),
             cache: self.cache.clone(),
+            metrics: self.metrics.clone(),
         }))
     }
 
@@ -116,7 +120,12 @@ impl ExecutionPlan for CopyExec {
         context: Arc<TaskContext>,
     ) -> DataFusionResult<SendableRecordBatchStream> {
         let child_stream = self.input.execute(partition, context)?;
-        Ok(Box::pin(CopyStream::new(self.schema(), child_stream)))
+        Ok(Box::pin(CopyStream::new(
+            self,
+            self.schema(),
+            child_stream,
+            partition,
+        )))
     }
 
     fn statistics(&self) -> DataFusionResult<Statistics> {
@@ -130,24 +139,36 @@ impl ExecutionPlan for CopyExec {
     fn name(&self) -> &str {
         "CopyExec"
     }
+
+    fn metrics(&self) -> Option<MetricsSet> {
+        Some(self.metrics.clone_inner())
+    }
 }
 
 struct CopyStream {
     schema: SchemaRef,
     child_stream: SendableRecordBatchStream,
+    baseline_metrics: BaselineMetrics,
 }
 
 impl CopyStream {
-    fn new(schema: SchemaRef, child_stream: SendableRecordBatchStream) -> Self 
{
+    fn new(
+        exec: &CopyExec,
+        schema: SchemaRef,
+        child_stream: SendableRecordBatchStream,
+        partition: usize,
+    ) -> Self {
         Self {
             schema,
             child_stream,
+            baseline_metrics: BaselineMetrics::new(&exec.metrics, partition),
         }
     }
 
     // TODO: replace copy_or_cast_array with copy_array if upstream sort 
kernel fixes
     // dictionary array sorting issue.
     fn copy(&self, batch: RecordBatch) -> DataFusionResult<RecordBatch> {
+        let mut timer = self.baseline_metrics.elapsed_compute().timer();
         let vectors = batch
             .columns()
             .iter()
@@ -155,8 +176,11 @@ impl CopyStream {
             .collect::<Result<Vec<ArrayRef>, _>>()?;
 
         let options = 
RecordBatchOptions::new().with_row_count(Some(batch.num_rows()));
-        RecordBatch::try_new_with_options(self.schema.clone(), vectors, 
&options)
-            .map_err(|e| arrow_datafusion_err!(e))
+        let maybe_batch = 
RecordBatch::try_new_with_options(self.schema.clone(), vectors, &options)
+            .map_err(|e| arrow_datafusion_err!(e));
+        timer.stop();
+        self.baseline_metrics.record_output(batch.num_rows());
+        maybe_batch
     }
 }
 
diff --git a/native/core/src/execution/operators/scan.rs 
b/native/core/src/execution/operators/scan.rs
index 68dd773c..d9212cf5 100644
--- a/native/core/src/execution/operators/scan.rs
+++ b/native/core/src/execution/operators/scan.rs
@@ -38,6 +38,7 @@ use crate::{
     },
     jvm_bridge::{jni_call, JVMClasses},
 };
+use datafusion::physical_plan::metrics::{BaselineMetrics, 
ExecutionPlanMetricsSet, MetricsSet};
 use datafusion::{
     execution::TaskContext,
     physical_expr::*,
@@ -62,6 +63,7 @@ pub struct ScanExec {
     /// It is also used in unit test to mock the input data from JVM.
     pub batch: Arc<Mutex<Option<InputBatch>>>,
     cache: PlanProperties,
+    metrics: ExecutionPlanMetricsSet,
 }
 
 impl ScanExec {
@@ -91,6 +93,7 @@ impl ScanExec {
             data_types,
             batch: Arc::new(Mutex::new(Some(first_batch))),
             cache,
+            metrics: ExecutionPlanMetricsSet::default(),
         })
     }
 
@@ -261,10 +264,14 @@ impl ExecutionPlan for ScanExec {
 
     fn execute(
         &self,
-        _: usize,
+        partition: usize,
         _: Arc<TaskContext>,
     ) -> datafusion::common::Result<SendableRecordBatchStream> {
-        Ok(Box::pin(ScanStream::new(self.clone(), self.schema())))
+        Ok(Box::pin(ScanStream::new(
+            self.clone(),
+            self.schema(),
+            partition,
+        )))
     }
 
     fn properties(&self) -> &PlanProperties {
@@ -274,6 +281,10 @@ impl ExecutionPlan for ScanExec {
     fn name(&self) -> &str {
         "ScanExec"
     }
+
+    fn metrics(&self) -> Option<MetricsSet> {
+        Some(self.metrics.clone_inner())
+    }
 }
 
 impl DisplayAs for ScanExec {
@@ -300,11 +311,18 @@ struct ScanStream {
     scan: ScanExec,
     /// Schema representing the data
     schema: SchemaRef,
+    /// Metrics
+    baseline_metrics: BaselineMetrics,
 }
 
 impl ScanStream {
-    pub fn new(scan: ScanExec, schema: SchemaRef) -> Self {
-        Self { scan, schema }
+    pub fn new(scan: ScanExec, schema: SchemaRef, partition: usize) -> Self {
+        let baseline_metrics = BaselineMetrics::new(&scan.metrics, partition);
+        Self {
+            scan,
+            schema,
+            baseline_metrics,
+        }
     }
 
     fn build_record_batch(
@@ -338,9 +356,11 @@ impl Stream for ScanStream {
     type Item = DataFusionResult<RecordBatch>;
 
     fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> 
Poll<Option<Self::Item>> {
+        let mut timer = self.baseline_metrics.elapsed_compute().timer();
         let mut scan_batch = self.scan.batch.try_lock().unwrap();
-        let input_batch = &*scan_batch;
+        timer.stop();
 
+        let input_batch = &*scan_batch;
         let input_batch = if let Some(batch) = input_batch {
             batch
         } else {
@@ -350,7 +370,11 @@ impl Stream for ScanStream {
         let result = match input_batch {
             InputBatch::EOF => Poll::Ready(None),
             InputBatch::Batch(columns, num_rows) => {
-                Poll::Ready(Some(self.build_record_batch(columns, *num_rows)))
+                self.baseline_metrics.record_output(*num_rows);
+                let mut timer = 
self.baseline_metrics.elapsed_compute().timer();
+                let maybe_batch = self.build_record_batch(columns, *num_rows);
+                timer.stop();
+                Poll::Ready(Some(maybe_batch))
             }
         };
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to