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

zclll 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 b082105d22a [env](compiler)educe template instantiations in datetime 
floor/ceil functions (#61515)
b082105d22a is described below

commit b082105d22ac45364d9fd0d33cc8daf7ac3f8da1
Author: Mryange <[email protected]>
AuthorDate: Wed Mar 25 10:23:32 2026 +0800

    [env](compiler)educe template instantiations in datetime floor/ceil 
functions (#61515)
    
    `function_datetime_floor_ceil.cpp` has excessive template instantiation
    bloat. The class `FunctionDateTimeFloorCeil<Flag, PType, ArgNum,
    UseDelta>` has 4 template parameters, producing 192 instantiations.
    However, all heavy computation functions (9 `vector_*` variants,
    `time_round_two_args`, `floor_opt`, etc.) only depend on `Flag` and
    `PType` โ€” they never use `ArgNum` or `UseDelta`. This means these
    expensive functions are compiled 4x more than necessary.
    
    This PR applies three optimizations:
    
    1. **Extract `DateTimeFloorCeilCore<Flag, PType>` struct**: All heavy
    computation functions are moved into a separate struct with only 2
    template parameters. `FunctionDateTimeFloorCeil` becomes a thin shell
    that delegates to `Core::vector_*()`. This reduces instantiations of the
    heaviest code from **192 โ†’ 48** (รท4).
    
    2. **Extract `convert_utc_to_local_impl<DateValueType>` free function**:
    This function only depends on `DateValueType`, not
    `Flag`/`ArgNum`/`UseDelta`. Extracting it reduces its instantiations
    from 192 โ†’ 3.
    
    3. **Extract `FunctionDateTimeFloorCeilBase` non-template base class**:
    Three virtual overrides (`get_number_of_arguments`, `is_variadic`,
    `use_default_implementation_for_nulls`) use zero template parameters.
    Moving them to a non-template base eliminates 192 redundant copies.
---
 .../function/function_datetime_floor_ceil.cpp      | 102 ++++++++++++---------
 1 file changed, 59 insertions(+), 43 deletions(-)

diff --git a/be/src/exprs/function/function_datetime_floor_ceil.cpp 
b/be/src/exprs/function/function_datetime_floor_ceil.cpp
index db9abb8941f..675af47a171 100644
--- a/be/src/exprs/function/function_datetime_floor_ceil.cpp
+++ b/be/src/exprs/function/function_datetime_floor_ceil.cpp
@@ -95,12 +95,41 @@ struct YearFloor;
 #define CEIL 1
 #endif
 
+// UTC to local time conversion - only depends on DateValueType, not all 
template params
+template <typename DateValueType>
+void convert_utc_to_local_impl(const DateValueType& utc_val, DateValueType& 
local_val,
+                               const cctz::time_zone& tz) {
+    cctz::time_point<cctz::sys_seconds> utc_tp =
+            cctz::convert(cctz::civil_second(utc_val.year(), utc_val.month(), 
utc_val.day(),
+                                             utc_val.hour(), utc_val.minute(), 
utc_val.second()),
+                          cctz::utc_time_zone());
+    auto local_cs = cctz::convert(utc_tp, tz);
+    local_val.unchecked_set_time(
+            static_cast<uint16_t>(local_cs.year()), 
static_cast<uint8_t>(local_cs.month()),
+            static_cast<uint8_t>(local_cs.day()), 
static_cast<uint8_t>(local_cs.hour()),
+            static_cast<uint8_t>(local_cs.minute()), 
static_cast<uint8_t>(local_cs.second()),
+            utc_val.microsecond());
+}
+
+// Base class: non-template overrides shared by all instantiations
+class FunctionDateTimeFloorCeilBase : public IFunction {
+public:
+    size_t get_number_of_arguments() const override { return 0; }
+    bool is_variadic() const override { return true; }
+    bool use_default_implementation_for_nulls() const override { return false; 
}
+};
+
+// Forward declaration of core computation struct (only depends on Flag + 
PType)
+template <typename Flag, PrimitiveType PType>
+struct DateTimeFloorCeilCore;
+
 template <typename Flag, PrimitiveType PType, int ArgNum, bool UseDelta = 
false>
-class FunctionDateTimeFloorCeil : public IFunction {
+class FunctionDateTimeFloorCeil : public FunctionDateTimeFloorCeilBase {
 public:
     using DateType = typename PrimitiveTypeTraits<PType>::DataType;
     using DateValueType = typename PrimitiveTypeTraits<PType>::CppType;
     using DeltaDataType = DataTypeInt32;
+    using Core = DateTimeFloorCeilCore<Flag, PType>;
     // return date type = DateType
     static constexpr auto name = Flag::name;
 
@@ -108,12 +137,6 @@ public:
 
     String get_name() const override { return name; }
 
-    size_t get_number_of_arguments() const override { return 0; }
-
-    bool is_variadic() const override { return true; }
-
-    bool use_default_implementation_for_nulls() const override { return false; 
}
-
     DataTypePtr get_return_type_impl(const DataTypes& arguments) const 
override {
         return have_nullable(arguments) ? 
make_nullable(std::make_shared<DateType>())
                                         : std::make_shared<DateType>();
@@ -178,7 +201,7 @@ public:
         col_to->resize(input_rows_count);
 
         if constexpr (ArgNum == 1) {
-            vector(sources->get_data(), col_to->get_data(), result_null_map, 
context);
+            Core::vector(sources->get_data(), col_to->get_data(), 
result_null_map, context);
         } else if constexpr (ArgNum == 2) {
             const IColumn& delta_column = *argument_columns[1];
             if (col_const[1]) {
@@ -191,25 +214,26 @@ public:
                     if (period < 1 && !period_is_null) [[unlikely]] {
                         throw_out_of_bound_int(Flag::name, period);
                     }
-                    vector_const_period(sources->get_data(), period, 
col_to->get_data(),
-                                        result_null_map, context);
+                    Core::vector_const_period(sources->get_data(), period, 
col_to->get_data(),
+                                              result_null_map, context);
                 } else {
                     // time_round(datetime, const(origin))
-                    vector_const_anchor(sources->get_data(), 
(*argument_columns[1])[0].get<PType>(),
-                                        col_to->get_data(), result_null_map, 
context);
+                    Core::vector_const_anchor(sources->get_data(),
+                                              
(*argument_columns[1])[0].get<PType>(),
+                                              col_to->get_data(), 
result_null_map, context);
                 }
             } else {
                 if (const auto* delta_vec_column0 =
                             
check_and_get_column<ColumnVector<PType>>(delta_column)) {
                     // time_round(datetime, origin)
-                    vector_vector_anchor(sources->get_data(), 
delta_vec_column0->get_data(),
-                                         col_to->get_data(), result_null_map, 
context);
+                    Core::vector_vector_anchor(sources->get_data(), 
delta_vec_column0->get_data(),
+                                               col_to->get_data(), 
result_null_map, context);
                 } else {
                     const auto* delta_vec_column1 = 
check_and_get_column<ColumnInt32>(delta_column);
                     DCHECK(delta_vec_column1 != nullptr);
                     // time_round(datetime, period)
-                    vector_vector_period(sources->get_data(), 
delta_vec_column1->get_data(),
-                                         col_to->get_data(), result_null_map, 
context);
+                    Core::vector_vector_period(sources->get_data(), 
delta_vec_column1->get_data(),
+                                               col_to->get_data(), 
result_null_map, context);
                 }
             }
         } else { // 3 arg, time_round(datetime, period, origin)
@@ -222,8 +246,8 @@ public:
                 if (period < 1 && !period_is_null) [[unlikely]] {
                     throw_out_of_bound_int(Flag::name, period);
                 }
-                vector_const_const(sources->get_data(), period, origin, 
col_to->get_data(),
-                                   result_null_map, context);
+                Core::vector_const_const(sources->get_data(), period, origin, 
col_to->get_data(),
+                                         result_null_map, context);
             } else if (col_const[1] && !col_const[2]) {
                 const auto arg2_column =
                         
check_and_get_column<ColumnVector<PType>>(*argument_columns[2]);
@@ -234,14 +258,14 @@ public:
                 if (period < 1 && !period_is_null) [[unlikely]] {
                     throw_out_of_bound_int(Flag::name, period);
                 }
-                vector_const_vector(sources->get_data(), period, 
arg2_column->get_data(),
-                                    col_to->get_data(), result_null_map, 
context);
+                Core::vector_const_vector(sources->get_data(), period, 
arg2_column->get_data(),
+                                          col_to->get_data(), result_null_map, 
context);
             } else if (!col_const[1] && col_const[2]) {
                 const auto* arg1_column = 
check_and_get_column<ColumnInt32>(*argument_columns[1]);
                 // time_round(datetime, period, const(origin))
-                vector_vector_const(sources->get_data(), 
arg1_column->get_data(),
-                                    (*argument_columns[2])[0].get<PType>(), 
col_to->get_data(),
-                                    result_null_map, context);
+                Core::vector_vector_const(sources->get_data(), 
arg1_column->get_data(),
+                                          
(*argument_columns[2])[0].get<PType>(),
+                                          col_to->get_data(), result_null_map, 
context);
             } else {
                 const auto* arg1_column = 
check_and_get_column<ColumnInt32>(*argument_columns[1]);
                 const auto arg2_column =
@@ -249,9 +273,9 @@ public:
                 DCHECK(arg1_column != nullptr);
                 DCHECK(arg2_column != nullptr);
                 // time_round(datetime, period, origin)
-                vector_vector_vector(sources->get_data(), 
arg1_column->get_data(),
-                                     arg2_column->get_data(), 
col_to->get_data(), result_null_map,
-                                     context);
+                Core::vector_vector_vector(sources->get_data(), 
arg1_column->get_data(),
+                                           arg2_column->get_data(), 
col_to->get_data(),
+                                           result_null_map, context);
             }
         }
 
@@ -265,8 +289,14 @@ public:
 
         return Status::OK();
     }
+};
+
+// Core computation struct - only depends on Flag + PType (not 
ArgNum/UseDelta).
+// This reduces template instantiations from 192 to 48 for all heavy 
computation functions.
+template <typename Flag, PrimitiveType PType>
+struct DateTimeFloorCeilCore {
+    using DateValueType = typename PrimitiveTypeTraits<PType>::CppType;
 
-private:
     static void vector(const PaddedPODArray<DateValueType>& dates,
                        PaddedPODArray<DateValueType>& res, const NullMap& 
result_null_map,
                        FunctionContext* context) {
@@ -532,12 +562,12 @@ private:
         const cctz::time_zone& tz = context->state()->timezone_obj();
 
         if constexpr (need_tz_conversion) {
-            convert_utc_to_local(ts_arg, local_arg, tz);
+            convert_utc_to_local_impl(ts_arg, local_arg, tz);
 
             if (ts_origin == TimestampTzValue::FIRST_DAY) {
                 local_origin = ts_origin;
             } else {
-                convert_utc_to_local(ts_origin, local_origin, tz);
+                convert_utc_to_local_impl(ts_origin, local_origin, tz);
             }
         }
 
@@ -891,20 +921,6 @@ private:
             }
         }
     }
-
-    static void convert_utc_to_local(const DateValueType& utc_val, 
DateValueType& local_val,
-                                     const cctz::time_zone& tz) {
-        cctz::time_point<cctz::sys_seconds> utc_tp = cctz::convert(
-                cctz::civil_second(utc_val.year(), utc_val.month(), 
utc_val.day(), utc_val.hour(),
-                                   utc_val.minute(), utc_val.second()),
-                cctz::utc_time_zone());
-        auto local_cs = cctz::convert(utc_tp, tz);
-        local_val.unchecked_set_time(
-                static_cast<uint16_t>(local_cs.year()), 
static_cast<uint8_t>(local_cs.month()),
-                static_cast<uint8_t>(local_cs.day()), 
static_cast<uint8_t>(local_cs.hour()),
-                static_cast<uint8_t>(local_cs.minute()), 
static_cast<uint8_t>(local_cs.second()),
-                utc_val.microsecond());
-    }
 };
 
 #define TIME_ROUND_WITH_DELTA_TYPE(IMPL, NAME, UNIT, TYPE, DELTA)              
                  \


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

Reply via email to