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]
