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

BiteTheDDDDt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new c8b81647776 [improvement](be) Track Python UDF Arrow memory 
allocations (#65361)
c8b81647776 is described below

commit c8b81647776bcd482b99665530f9fd5ba41f0d03
Author: Pxl <[email protected]>
AuthorDate: Wed Jul 15 23:25:28 2026 +0800

    [improvement](be) Track Python UDF Arrow memory allocations (#65361)
    
    Problem Summary: Python UDF/UDAF/UDTF input and request batch
    construction used Arrow's default memory pool, so Arrow buffers
    allocated while preparing Python function requests could bypass Doris
    memory tracking.
    
    This PR switches the synchronous Python UDF/UDAF/UDTF Arrow batch
    construction paths to `ExecEnv::GetInstance()->arrow_memory_pool()`.
    
    Benefits:
    - Routes these Arrow buffer allocations through Doris' BE Arrow memory
    pool, which is backed by Doris Allocator and memory tracker.
    - Keeps Python function request/input batch memory accounting consistent
    with other Doris Arrow integration paths.
    - Avoids changing Python UDF/UDAF/UDTF semantics; this only changes the
    allocator used for in-process Arrow buffers.
---
 be/src/exprs/aggregate/aggregate_function_python_udaf.cpp | 11 +++++++----
 be/src/exprs/function/function_python_udf.cpp             |  4 +++-
 be/src/exprs/table_function/python_udtf_function.cpp      |  5 +++--
 be/src/udf/python/python_udaf_client.cpp                  | 13 +++++++------
 4 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/be/src/exprs/aggregate/aggregate_function_python_udaf.cpp 
b/be/src/exprs/aggregate/aggregate_function_python_udaf.cpp
index 4b6917f3962..cf27191ebe7 100644
--- a/be/src/exprs/aggregate/aggregate_function_python_udaf.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_python_udaf.cpp
@@ -33,6 +33,7 @@
 #include "core/data_type/define_primitive_type.h"
 #include "format/arrow/arrow_block_convertor.h"
 #include "format/arrow/arrow_row_batch.h"
+#include "runtime/exec_env.h"
 #include "runtime/user_function_cache.h"
 #include "udf/python/python_env.h"
 #include "udf/python/python_server.h"
@@ -66,8 +67,9 @@ Status AggregatePythonUDAFData::add(int64_t place_id, const 
IColumn** columns,
 
     std::shared_ptr<arrow::RecordBatch> batch;
     // Zero-copy: convert only the specified range
-    RETURN_IF_ERROR(convert_to_arrow_batch(input_block, schema, 
arrow::default_memory_pool(),
-                                           &batch, timezone_obj, 
row_num_start, row_num_end));
+    RETURN_IF_ERROR(convert_to_arrow_batch(input_block, schema,
+                                           
ExecEnv::GetInstance()->arrow_memory_pool(), &batch,
+                                           timezone_obj, row_num_start, 
row_num_end));
     // Send the batch (already sliced in convert_to_arrow_batch)
     // Single place mode: no places column needed
     RETURN_IF_ERROR(client->accumulate(place_id, true, *batch, 0, 
batch->num_rows()));
@@ -111,8 +113,9 @@ Status AggregatePythonUDAFData::add_batch(AggregateDataPtr* 
places, size_t place
     std::shared_ptr<arrow::RecordBatch> batch;
     // Zero-copy: convert only the [start, end) range
     // This slice includes the places column automatically
-    RETURN_IF_ERROR(convert_to_arrow_batch(input_block, schema, 
arrow::default_memory_pool(),
-                                           &batch, timezone_obj, start, end));
+    RETURN_IF_ERROR(convert_to_arrow_batch(input_block, schema,
+                                           
ExecEnv::GetInstance()->arrow_memory_pool(), &batch,
+                                           timezone_obj, start, end));
     // Send entire batch (already contains places column) to Python
     // place_id=0 is ignored when is_single_place=false
     RETURN_IF_ERROR(client->accumulate(0, false, *batch, 0, slice_rows));
diff --git a/be/src/exprs/function/function_python_udf.cpp 
b/be/src/exprs/function/function_python_udf.cpp
index 54ea74ad456..ca9fa280f08 100644
--- a/be/src/exprs/function/function_python_udf.cpp
+++ b/be/src/exprs/function/function_python_udf.cpp
@@ -30,6 +30,7 @@
 #include "common/status.h"
 #include "core/block/block.h"
 #include "format/arrow/arrow_block_convertor.h"
+#include "runtime/exec_env.h"
 #include "runtime/user_function_cache.h"
 #include "udf/python/python_server.h"
 #include "udf/python/python_udf_client.h"
@@ -144,7 +145,8 @@ Status PythonFunctionCall::execute_impl(FunctionContext* 
context, Block& block,
     if (arguments.empty()) {
         RETURN_IF_ERROR(make_zero_column_arrow_batch(schema, input_rows, 
&input_batch));
     } else {
-        RETURN_IF_ERROR(convert_to_arrow_batch(input_block, schema, 
arrow::default_memory_pool(),
+        RETURN_IF_ERROR(convert_to_arrow_batch(input_block, schema,
+                                               
ExecEnv::GetInstance()->arrow_memory_pool(),
                                                &input_batch, _timezone_obj));
     }
     RETURN_IF_ERROR(client->evaluate(*input_batch, &output_batch));
diff --git a/be/src/exprs/table_function/python_udtf_function.cpp 
b/be/src/exprs/table_function/python_udtf_function.cpp
index eaaf4d5227a..fbbea4bfc81 100644
--- a/be/src/exprs/table_function/python_udtf_function.cpp
+++ b/be/src/exprs/table_function/python_udtf_function.cpp
@@ -38,6 +38,7 @@
 #include "format/arrow/arrow_block_convertor.h"
 #include "format/arrow/arrow_row_batch.h"
 #include "format/arrow/arrow_utils.h"
+#include "runtime/exec_env.h"
 #include "runtime/runtime_state.h"
 #include "runtime/user_function_cache.h"
 #include "udf/python/python_env.h"
@@ -141,8 +142,8 @@ Status PythonUDTFFunction::process_init(Block* block, 
RuntimeState* state) {
         RETURN_IF_ERROR(make_zero_column_arrow_batch(input_schema, input_rows, 
&input_batch));
     } else {
         RETURN_IF_ERROR(convert_to_arrow_batch(input_block, input_schema,
-                                               arrow::default_memory_pool(), 
&input_batch,
-                                               _timezone_obj));
+                                               
ExecEnv::GetInstance()->arrow_memory_pool(),
+                                               &input_batch, _timezone_obj));
     }
 
     // Step 3: Call Python UDTF to evaluate all rows at once (similar to Java 
UDTF's JNI call)
diff --git a/be/src/udf/python/python_udaf_client.cpp 
b/be/src/udf/python/python_udaf_client.cpp
index 4308750ccec..d334017415b 100644
--- a/be/src/udf/python/python_udaf_client.cpp
+++ b/be/src/udf/python/python_udaf_client.cpp
@@ -30,6 +30,7 @@
 #include "common/compiler_util.h"
 #include "common/status.h"
 #include "format/arrow/arrow_utils.h"
+#include "runtime/exec_env.h"
 #include "udf/python/python_udf_meta.h"
 #include "udf/python/python_udf_runtime.h"
 #include "util/unaligned.h"
@@ -509,7 +510,7 @@ Status PythonUDAFClient::_create_data_request_batch(const 
arrow::RecordBatch& in
         columns.push_back(input_data.column(num_input_columns - 1));
     } else {
         // Create NULL places column for single-place mode
-        arrow::Int64Builder places_builder;
+        arrow::Int64Builder 
places_builder(ExecEnv::GetInstance()->arrow_memory_pool());
         std::shared_ptr<arrow::Array> places_array;
         
RETURN_DORIS_STATUS_IF_ERROR(places_builder.AppendNulls(input_data.num_rows()));
         RETURN_DORIS_STATUS_IF_ERROR(places_builder.Finish(&places_array));
@@ -517,7 +518,7 @@ Status PythonUDAFClient::_create_data_request_batch(const 
arrow::RecordBatch& in
     }
 
     // Add NULL binary_data column
-    arrow::BinaryBuilder binary_builder;
+    arrow::BinaryBuilder 
binary_builder(ExecEnv::GetInstance()->arrow_memory_pool());
     std::shared_ptr<arrow::Array> binary_array;
     
RETURN_DORIS_STATUS_IF_ERROR(binary_builder.AppendNulls(input_data.num_rows()));
     RETURN_DORIS_STATUS_IF_ERROR(binary_builder.Finish(&binary_array));
@@ -538,7 +539,7 @@ Status PythonUDAFClient::_create_binary_request_batch(
     for (int i = 0; i < num_data_columns; ++i) {
         std::unique_ptr<arrow::ArrayBuilder> builder;
         std::shared_ptr<arrow::Array> null_array;
-        
RETURN_DORIS_STATUS_IF_ERROR(arrow::MakeBuilder(arrow::default_memory_pool(),
+        
RETURN_DORIS_STATUS_IF_ERROR(arrow::MakeBuilder(ExecEnv::GetInstance()->arrow_memory_pool(),
                                                         
_schema->field(i)->type(), &builder));
         RETURN_DORIS_STATUS_IF_ERROR(builder->AppendNull());
         RETURN_DORIS_STATUS_IF_ERROR(builder->Finish(&null_array));
@@ -546,7 +547,7 @@ Status PythonUDAFClient::_create_binary_request_batch(
     }
 
     // Create binary_data column
-    arrow::BinaryBuilder binary_builder;
+    arrow::BinaryBuilder 
binary_builder(ExecEnv::GetInstance()->arrow_memory_pool());
     std::shared_ptr<arrow::Array> binary_array;
     RETURN_DORIS_STATUS_IF_ERROR(
             binary_builder.Append(binary_data->data(), 
static_cast<int32_t>(binary_data->size())));
@@ -571,8 +572,8 @@ Status 
PythonUDAFClient::_get_empty_request_batch(std::shared_ptr<arrow::RecordB
         auto field = _schema->field(i);
         std::unique_ptr<arrow::ArrayBuilder> builder;
         std::shared_ptr<arrow::Array> null_array;
-        RETURN_DORIS_STATUS_IF_ERROR(
-                arrow::MakeBuilder(arrow::default_memory_pool(), 
field->type(), &builder));
+        
RETURN_DORIS_STATUS_IF_ERROR(arrow::MakeBuilder(ExecEnv::GetInstance()->arrow_memory_pool(),
+                                                        field->type(), 
&builder));
         RETURN_DORIS_STATUS_IF_ERROR(builder->AppendNull());
         RETURN_DORIS_STATUS_IF_ERROR(builder->Finish(&null_array));
         columns.push_back(null_array);


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

Reply via email to