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

kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 8ad03233cfdd682a23326ba74f47471bca0dbfe9
Author: Mryange <[email protected]>
AuthorDate: Tue Aug 15 13:16:42 2023 +0800

    [performance](executor) optimize time_round function only one arg (#22855)
---
 .../vec/functions/function_datetime_floor_ceil.cpp | 107 +++++++++++++++++++-
 be/src/vec/runtime/vdatetime_value.cpp             | 110 +++++++++++++++++++++
 be/src/vec/runtime/vdatetime_value.h               |   9 ++
 3 files changed, 225 insertions(+), 1 deletion(-)

diff --git a/be/src/vec/functions/function_datetime_floor_ceil.cpp 
b/be/src/vec/functions/function_datetime_floor_ceil.cpp
index a2389295cd..0e4518f2d0 100644
--- a/be/src/vec/functions/function_datetime_floor_ceil.cpp
+++ b/be/src/vec/functions/function_datetime_floor_ceil.cpp
@@ -215,7 +215,18 @@ struct FloorCeilImpl {
     template <typename NativeType>
     static void vector(const PaddedPODArray<NativeType>& dates, 
PaddedPODArray<NativeType>& res,
                        NullMap& null_map) {
-        vector_constant_delta<NativeType, Int32>(dates, Int32(1), res, 
null_map);
+        // vector_constant_delta<NativeType, Int32>(dates, Int32(1), res, 
null_map);
+        for (int i = 0; i < dates.size(); ++i) {
+            if constexpr (std::is_same_v<NativeType, UInt32>) {
+                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(dates[i], res[i],
+                                                                               
 null_map[i]);
+            } else if constexpr (std::is_same_v<NativeType, UInt64>) {
+                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
+                        dates[i], res[i], null_map[i]);
+            } else {
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
res[i], null_map[i]);
+            }
+        }
     }
 
     template <typename NativeType>
@@ -474,6 +485,83 @@ struct TimeRound {
         is_null = !ts1.template date_add_interval<Impl::Unit>(interval);
     }
 
+    static constexpr uint64_t MASK_DAY_FLOOR =
+            0b1111111111111111111111111110000000000000000000000000000000000000;
+    static constexpr uint64_t MASK_HOUR_FLOOR =
+            0b1111111111111111111111111111111100000000000000000000000000000000;
+    static constexpr uint64_t MASK_MINUTE_FLOOR =
+            0b1111111111111111111111111111111111111100000000000000000000000000;
+    static constexpr uint64_t MASK_SECOND_FLOOR =
+            0b1111111111111111111111111111111111111111111100000000000000000000;
+
+    static constexpr bool USE_OPTIMIZE_FLOOR =
+            Impl::Unit == DAY || Impl::Unit == HOUR || Impl::Unit == MINUTE || 
Impl::Unit == SECOND;
+    template <typename NativeType, typename DateValueType>
+    static void datetimev2_floor(const DateValueType& ts2, DateValueType& ts1) 
{
+        // Optimize the performance of the datetimev2 type on the floor 
operation.
+        // Now supports days, hours, minutes, and seconds.
+        if constexpr (Impl::Unit == DAY) {
+            ts1.set_int_val(ts2.to_date_int_val() & MASK_DAY_FLOOR);
+        }
+        if constexpr (Impl::Unit == HOUR) {
+            ts1.set_int_val(ts2.to_date_int_val() & MASK_HOUR_FLOOR);
+        }
+        if constexpr (Impl::Unit == MINUTE) {
+            ts1.set_int_val(ts2.to_date_int_val() & MASK_MINUTE_FLOOR);
+        }
+        if constexpr (Impl::Unit == SECOND) {
+            ts1.set_int_val(ts2.to_date_int_val() & MASK_SECOND_FLOOR);
+        }
+    }
+    template <typename NativeType, typename DateValueType>
+    static void time_round(const DateValueType& ts2, DateValueType& ts1, 
UInt8& is_null) {
+        static_assert(Impl::Unit != WEEK);
+        if constexpr (std::is_same_v<DateValueType, 
DateV2Value<DateTimeV2ValueType>> &&
+                      Impl::Type == FLOOR && USE_OPTIMIZE_FLOOR) {
+            datetimev2_floor<NativeType, DateValueType>(ts2, ts1);
+            is_null = false;
+            return;
+        };
+        int64_t diff;
+        int64_t part;
+        if constexpr (Impl::Unit == YEAR) {
+            diff = ts2.year();
+            part = (ts2.month() - 1) + (ts2.day() - 1) + ts2.hour() + 
ts2.minute() + ts2.second();
+        }
+        if constexpr (Impl::Unit == MONTH) {
+            diff = ts2.year() * 12 + ts2.month() - 1;
+            part = (ts2.day() - 1) + ts2.hour() + ts2.minute() + ts2.second();
+        }
+        if constexpr (Impl::Unit == DAY) {
+            diff = ts2.daynr();
+            part = ts2.hour() + ts2.minute() + ts2.second();
+        }
+        if constexpr (Impl::Unit == HOUR) {
+            diff = ts2.daynr() * 24 + ts2.hour();
+            part = ts2.minute() + ts2.second();
+        }
+        if constexpr (Impl::Unit == MINUTE) {
+            diff = ts2.daynr() * 24L * 60 + ts2.hour() * 60 + ts2.minute();
+            part = ts2.second();
+        }
+        if constexpr (Impl::Unit == SECOND) {
+            diff = ts2.daynr() * 24L * 60 * 60 + ts2.hour() * 60L * 60 + 
ts2.minute() * 60L +
+                   ts2.second();
+            part = 0;
+            if constexpr (std::is_same_v<DateValueType, 
DateV2Value<DateTimeV2ValueType>>) {
+                part = ts2.microsecond();
+            }
+        }
+
+        if constexpr (Impl::Type == CEIL) {
+            if (part) {
+                diff++;
+            }
+        }
+        TimeInterval interval(Impl::Unit, diff, 1);
+        is_null = !ts1.template date_set_interval<Impl::Unit>(interval);
+    }
+
     template <typename NativeType, typename DateValueType>
     static void time_round(NativeType date, Int32 period, NativeType 
origin_date, NativeType& res,
                            UInt8& is_null) {
@@ -504,6 +592,23 @@ struct TimeRound {
 
         TimeRound<Impl>::template time_round<NativeType, DateValueType>(ts2, 
period, ts1, is_null);
     }
+
+    template <typename NativeType, typename DateValueType>
+    static void time_round(NativeType date, NativeType& res, UInt8& is_null) {
+        auto ts2 = binary_cast<NativeType, DateValueType>(date);
+        if (!ts2.is_valid_date()) {
+            is_null = true;
+            return;
+        }
+        auto& ts1 = (DateValueType&)(res);
+        if constexpr (Impl::Unit != WEEK) {
+            TimeRound<Impl>::template time_round<NativeType, 
DateValueType>(ts2, ts1, is_null);
+        } else {
+            // Only week use the FIRST SUNDAY
+            ts1.from_olap_datetime(FIRST_SUNDAY);
+            TimeRound<Impl>::template time_round<NativeType, 
DateValueType>(ts2, 1, ts1, is_null);
+        }
+    }
 };
 
 #define TIME_ROUND_WITH_DELTA_TYPE(CLASS, NAME, UNIT, TYPE, DELTA)             
                    \
diff --git a/be/src/vec/runtime/vdatetime_value.cpp 
b/be/src/vec/runtime/vdatetime_value.cpp
index 9675ab63fa..e23cad1e2b 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -1671,6 +1671,50 @@ bool VecDateTimeValue::date_add_interval(const 
TimeInterval& interval) {
     return true;
 }
 
+template <TimeUnit unit>
+bool VecDateTimeValue::date_set_interval(const TimeInterval& interval) {
+    static_assert(
+            (unit == YEAR) || (unit == MONTH) || (unit == DAY) || (unit == 
HOUR) ||
+                    (unit == MINUTE) || (unit == SECOND),
+            "date_set_interval function now only support YEAR MONTH DAY HOUR 
MINUTE SECOND type");
+    if constexpr ((unit == SECOND) || (unit == MINUTE) || (unit == HOUR)) {
+        set_zero(type());
+        // This may change the day information
+        int64_t seconds = interval.day * 86400L + interval.hour * 3600 + 
interval.minute * 60 +
+                          interval.second;
+        int64_t days = seconds / 86400;
+        seconds %= 86400L;
+        _second = seconds % 60;
+        _minute = (seconds / 60) % 60;
+        _hour = seconds / 3600;
+        int64_t day_nr = doris::calc_daynr(_year, _month, 1) + days;
+        if (!get_date_from_daynr(day_nr)) {
+            return false;
+        }
+        if (_second || _minute || _hour) {
+            _type = TIME_DATETIME;
+        }
+    } else if constexpr ((unit == DAY)) {
+        // This only change day information, not change second information
+        int64_t day_nr = interval.day;
+        if (!get_date_from_daynr(day_nr)) {
+            return false;
+        }
+    } else if constexpr (unit == YEAR) {
+        // This only change year information
+        _year = interval.year;
+        _day = 1;
+        _month = 1;
+    } else if constexpr (unit == MONTH) {
+        // This will change month and year information, maybe date.
+        int64_t months = 12 * interval.year + interval.month;
+        _year = months / 12;
+        _day = 1;
+        _month = (months % 12) + 1;
+    }
+    return true;
+}
+
 bool VecDateTimeValue::unix_timestamp(int64_t* timestamp, const std::string& 
timezone) const {
     cctz::time_zone ctz;
     if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
@@ -2872,6 +2916,39 @@ bool DateV2Value<T>::date_add_interval(const 
TimeInterval& interval) {
     return true;
 }
 
+template <typename T>
+template <TimeUnit unit>
+bool DateV2Value<T>::date_set_interval(const TimeInterval& interval) {
+    static_assert(
+            (unit == YEAR) || (unit == MONTH) || (unit == DAY) || (unit == 
HOUR) ||
+                    (unit == MINUTE) || (unit == SECOND),
+            "date_set_interval function now only support YEAR MONTH DAY HOUR 
MINUTE SECOND type");
+    if constexpr ((unit == SECOND) || (unit == MINUTE) || (unit == HOUR) || 
(unit == DAY)) {
+        set_zero();
+        // This may change the day information
+        int64_t seconds = (interval.day * 86400 + interval.hour * 3600 + 
interval.minute * 60 +
+                           interval.second);
+        int64_t days = seconds / 86400;
+        seconds %= 86400L;
+        if (!this->get_date_from_daynr(days)) {
+            return false;
+        }
+        if constexpr (is_datetime) {
+            this->set_time(seconds / 3600, (seconds / 60) % 60, seconds % 60, 
0);
+        }
+    } else if constexpr (unit == YEAR) {
+        this->set_time(0, 1, 1, 0, 0, 0, 0);
+        this->template set_time_unit<TimeUnit::YEAR>(interval.year);
+    } else if constexpr (unit == MONTH) {
+        // This will change month and year information, maybe date.
+        this->set_time(0, 1, 1, 0, 0, 0, 0);
+        int64_t months = 12 * interval.year + interval.month;
+        this->template set_time_unit<TimeUnit::YEAR>(months / 12);
+        this->template set_time_unit<TimeUnit::MONTH>((months % 12) + 1);
+    }
+    return true;
+}
+
 template <typename T>
 template <TimeUnit unit>
 bool DateV2Value<T>::datetime_trunc() {
@@ -3636,6 +3713,39 @@ template bool 
DateV2Value<DateTimeV2ValueType>::date_add_interval<TimeUnit::QUAR
 template bool 
DateV2Value<DateTimeV2ValueType>::date_add_interval<TimeUnit::WEEK>(
         const TimeInterval& interval);
 
+template bool VecDateTimeValue::date_set_interval<TimeUnit::SECOND>(const 
TimeInterval& interval);
+template bool VecDateTimeValue::date_set_interval<TimeUnit::MINUTE>(const 
TimeInterval& interval);
+template bool VecDateTimeValue::date_set_interval<TimeUnit::HOUR>(const 
TimeInterval& interval);
+template bool VecDateTimeValue::date_set_interval<TimeUnit::DAY>(const 
TimeInterval& interval);
+template bool VecDateTimeValue::date_set_interval<TimeUnit::MONTH>(const 
TimeInterval& interval);
+template bool VecDateTimeValue::date_set_interval<TimeUnit::YEAR>(const 
TimeInterval& interval);
+
+template bool 
DateV2Value<DateV2ValueType>::date_set_interval<TimeUnit::SECOND>(
+        const TimeInterval& interval);
+template bool 
DateV2Value<DateV2ValueType>::date_set_interval<TimeUnit::MINUTE>(
+        const TimeInterval& interval);
+template bool DateV2Value<DateV2ValueType>::date_set_interval<TimeUnit::HOUR>(
+        const TimeInterval& interval);
+template bool DateV2Value<DateV2ValueType>::date_set_interval<TimeUnit::DAY>(
+        const TimeInterval& interval);
+template bool DateV2Value<DateV2ValueType>::date_set_interval<TimeUnit::MONTH>(
+        const TimeInterval& interval);
+template bool DateV2Value<DateV2ValueType>::date_set_interval<TimeUnit::YEAR>(
+        const TimeInterval& interval);
+
+template bool 
DateV2Value<DateTimeV2ValueType>::date_set_interval<TimeUnit::SECOND>(
+        const TimeInterval& interval);
+template bool 
DateV2Value<DateTimeV2ValueType>::date_set_interval<TimeUnit::MINUTE>(
+        const TimeInterval& interval);
+template bool 
DateV2Value<DateTimeV2ValueType>::date_set_interval<TimeUnit::HOUR>(
+        const TimeInterval& interval);
+template bool 
DateV2Value<DateTimeV2ValueType>::date_set_interval<TimeUnit::DAY>(
+        const TimeInterval& interval);
+template bool 
DateV2Value<DateTimeV2ValueType>::date_set_interval<TimeUnit::MONTH>(
+        const TimeInterval& interval);
+template bool 
DateV2Value<DateTimeV2ValueType>::date_set_interval<TimeUnit::YEAR>(
+        const TimeInterval& interval);
+
 template bool VecDateTimeValue::datetime_trunc<TimeUnit::SECOND>();
 template bool VecDateTimeValue::datetime_trunc<TimeUnit::MINUTE>();
 template bool VecDateTimeValue::datetime_trunc<TimeUnit::HOUR>();
diff --git a/be/src/vec/runtime/vdatetime_value.h 
b/be/src/vec/runtime/vdatetime_value.h
index 21e7a42d81..d71b78dbe2 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -481,6 +481,10 @@ public:
     template <TimeUnit unit>
     bool date_add_interval(const TimeInterval& interval);
 
+    // set interval
+    template <TimeUnit unit>
+    bool date_set_interval(const TimeInterval& interval);
+
     template <TimeUnit unit>
     bool datetime_trunc(); //datetime trunc, like trunc minute = 0
 
@@ -935,6 +939,9 @@ public:
     template <TimeUnit unit>
     bool date_add_interval(const TimeInterval& interval);
 
+    template <TimeUnit unit>
+    bool date_set_interval(const TimeInterval& interval);
+
     template <TimeUnit unit>
     bool datetime_trunc(); //datetime trunc, like trunc minute = 0
 
@@ -1161,6 +1168,8 @@ public:
 
     void format_datetime(uint32_t* date_v, bool* carry_bits) const;
 
+    void set_int_val(uint64_t val) { this->int_val_ = val; }
+
 private:
     static uint8_t calc_week(const uint32_t& day_nr, const uint16_t& year, 
const uint8_t& month,
                              const uint8_t& day, uint8_t mode, uint16_t* 
to_year,


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

Reply via email to