This is an automated email from the ASF dual-hosted git repository.
panxiaolei 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 2e34bee48bb [Exec](vec) speed update date_floor (#50392)
2e34bee48bb is described below
commit 2e34bee48bb8aef404408c685c9bbe9b10ae0f6d
Author: HappenLee <[email protected]>
AuthorDate: Mon May 5 21:45:56 2025 +0800
[Exec](vec) speed update date_floor (#50392)
### What problem does this PR solve?
before can div 60%:
```
mysql> select count(date_floor(l_commitdate, interval 5 minute)) from
lineitem;
+-----------------------------------------------------+
| count(date_floor(l_commitdate, interval 5 minute)) |
+-----------------------------------------------------+
| 600037902 |
+-----------------------------------------------------+
1 row in set (32.99 sec)
```
after can div:
```
mysql> select count(date_floor(l_commitdate, interval 5 minute)) from
lineitem;
+----------------------------------------------------+
| count(date_floor(l_commitdate, interval 5 minute)) |
+----------------------------------------------------+
| 600037902 |
+----------------------------------------------------+
1 row in set (6.10 sec)
```
### Release note
None
### Check List (For Author)
- Test <!-- At least one of them must be included. -->
- [ ] Regression test
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [x] No need to test or manual test. Explain why:
- [x] This is a refactor/code format and no logic has been changed.
- [ ] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason <!-- Add your reason? -->
- Behavior changed:
- [x] No.
- [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
- [x] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
---
be/src/util/time_lut.cpp | 29 ----------
be/src/util/time_lut.h | 2 -
.../vec/functions/function_datetime_floor_ceil.cpp | 65 ++++++++++++++++++----
be/src/vec/runtime/vdatetime_value.cpp | 23 +++-----
be/src/vec/runtime/vdatetime_value.h | 44 +++++++++++++--
5 files changed, 101 insertions(+), 62 deletions(-)
diff --git a/be/src/util/time_lut.cpp b/be/src/util/time_lut.cpp
index cb2aecb7289..9864dd9923b 100644
--- a/be/src/util/time_lut.cpp
+++ b/be/src/util/time_lut.cpp
@@ -91,35 +91,6 @@ uint8_t calc_weekday(uint64_t day_nr, bool
is_sunday_first_day) {
return (day_nr + 5L + (is_sunday_first_day ? 1L : 0L)) % 7;
}
-uint32_t calc_daynr(uint16_t year, uint8_t month, uint8_t day) {
- // date_day_offet_dict range from [1900-01-01, 2039-12-31]
- if (date_day_offset_dict::can_speed_up_calc_daynr(year) &&
- LIKELY(date_day_offset_dict::get_dict_init())) {
- return date_day_offset_dict::get().daynr(year, month, day);
- }
-
- uint32_t delsum = 0;
- int y = year;
-
- if (year == 0 && month == 0) {
- return 0;
- }
-
- /* Cast to int to be able to handle month == 0 */
- delsum = 365 * y + 31 * (month - 1) + day;
- if (month <= 2) {
- // No leap year
- y--;
- } else {
- // This is great!!!
- // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
- // 0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 7, 8
- delsum -= (month * 4 + 23) / 10;
- }
- // Every 400 year has 97 leap year, 100, 200, 300 are not leap year.
- return delsum + y / 4 - y / 100 + y / 400;
-}
-
uint32_t year_week(uint16_t yy, uint8_t month, uint8_t day) {
//not covered by year_week_table, calculate at runtime
uint16_t to_year = 0;
diff --git a/be/src/util/time_lut.h b/be/src/util/time_lut.h
index f98560c45e1..4764cf00220 100644
--- a/be/src/util/time_lut.h
+++ b/be/src/util/time_lut.h
@@ -32,8 +32,6 @@ constexpr uint32_t NUM_DAYS = 31;
uint32_t year_week(uint16_t yy, uint8_t month, uint8_t day);
-uint32_t calc_daynr(uint16_t year, uint8_t month, uint8_t day);
-
uint8_t calc_weekday(uint64_t day_nr, bool is_sunday_first_day);
inline bool is_leap(uint32_t year) {
diff --git a/be/src/vec/functions/function_datetime_floor_ceil.cpp
b/be/src/vec/functions/function_datetime_floor_ceil.cpp
index 0e5cd2f2f58..fad31b0e12c 100644
--- a/be/src/vec/functions/function_datetime_floor_ceil.cpp
+++ b/be/src/vec/functions/function_datetime_floor_ceil.cpp
@@ -178,7 +178,6 @@ public:
vector_const_const(sources->get_data(), arg1.get<Int32>(),
arg2.get<NativeType>(),
col_to->get_data(),
null_map->get_data());
-
} else if (arg1_const && !arg2_const) {
Field arg1;
arg1_col->get(0, arg1);
@@ -244,18 +243,42 @@ private:
memset(null_map.data(), 1, sizeof(UInt8) * dates.size());
return;
}
- for (int i = 0; i < dates.size(); ++i) {
- SET_NULLMAP_IF_FALSE((time_round_reinterpret_two_args(dates[i],
period, res[i])));
+
+ // expand codes for const input periods
+#define EXPAND_CODE_FOR_CONST_INPUT(X)
\
+ case X: {
\
+ for (int i = 0; i < dates.size(); ++i) {
\
+ SET_NULLMAP_IF_FALSE((time_round_reinterpret_two_args<X>(dates[i],
period, res[i]))); \
+ }
\
+ return;
\
+ }
+#define EXPANDER(z, n, text) EXPAND_CODE_FOR_CONST_INPUT(n)
+ switch (period) {
+ // expand for some constant period
+ BOOST_PP_REPEAT(12, EXPANDER, ~)
+ default:
+ for (int i = 0; i < dates.size(); ++i) {
+
SET_NULLMAP_IF_FALSE((time_round_reinterpret_two_args(dates[i], period,
res[i])));
+ }
}
+#undef EXPAND_CODE_FOR_CONST_INPUT
+#undef EXPANDER
}
static void vector_const_const(const PaddedPODArray<NativeType>& dates,
const Int32 period,
NativeType origin_date,
PaddedPODArray<NativeType>& res,
NullMap& null_map) {
+ if (auto cast_date = binary_cast<NativeType,
DateValueType>(origin_date);
+ cast_date == DateValueType::FIRST_DAY) {
+ vector_const_period(dates, period, res, null_map);
+ return;
+ }
+
if (period < 1) {
memset(null_map.data(), 1, sizeof(UInt8) * dates.size());
return;
}
+
// expand codes for const input periods
#define EXPAND_CODE_FOR_CONST_INPUT(X) \
case X: { \
@@ -264,7 +287,7 @@ private:
res[i] = origin_date; \
auto ts2 = binary_cast<NativeType, DateValueType>(dates[i]); \
auto& ts1 = (DateValueType&)(res[i]); \
- SET_NULLMAP_IF_FALSE(time_round_two_args(ts2, X, ts1)) \
+ SET_NULLMAP_IF_FALSE(time_round_two_args<X>(ts2, X, ts1)) \
} \
return; \
}
@@ -368,17 +391,27 @@ private:
}
}
- ALWAYS_INLINE static bool time_round_reinterpret_two_args(NativeType date,
Int32 period,
- NativeType& res)
{
+ template <int const_period = 0>
+ static bool time_round_reinterpret_two_args(NativeType date, Int32 period,
NativeType& res) {
auto ts_arg = binary_cast<NativeType, DateValueType>(date);
auto& ts_res = (DateValueType&)(res);
- if (can_use_optimize(period)) {
- floor_opt(ts_arg, ts_res, period);
- return true;
+ if constexpr (const_period == 0) {
+ if (can_use_optimize(period)) {
+ floor_opt(ts_arg, ts_res, period);
+ return true;
+ } else {
+ ts_res = DateValueType::FIRST_DAY;
+ return time_round_two_args(ts_arg, period, ts_res);
+ }
} else {
- ts_res = DateValueType::FIRST_DAY;
- return time_round_two_args(ts_arg, period, ts_res);
+ if (can_use_optimize(const_period)) {
+ floor_opt(ts_arg, ts_res, const_period);
+ return true;
+ } else {
+ ts_res = DateValueType::FIRST_DAY;
+ return time_round_two_args<const_period>(ts_arg, const_period,
ts_res);
+ }
}
}
@@ -443,6 +476,7 @@ private:
}
}
+ template <Int32 const_period = 0>
static bool time_round_two_args(const DateValueType& ts_arg, const Int32
period,
DateValueType& ts_res) {
int64_t diff;
@@ -582,7 +616,14 @@ private:
}
//round down/up inside time period(several time-units)
- int64_t delta_inside_period = diff >= 0 ? diff % period : (diff %
period + period) % period;
+ int64_t delta_inside_period;
+ if constexpr (const_period != 0) {
+ delta_inside_period = diff >= 0 ? diff % const_period
+ : (diff % const_period +
const_period) % const_period;
+ } else {
+ delta_inside_period = diff >= 0 ? diff % period : (diff % period +
period) % period;
+ }
+
int64_t step = diff - delta_inside_period +
(Flag::Type == FLOOR ? 0
: delta_inside_period == 0 ? 0
diff --git a/be/src/vec/runtime/vdatetime_value.cpp
b/be/src/vec/runtime/vdatetime_value.cpp
index 1b83a890c69..9e27c163876 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -2777,14 +2777,6 @@ bool date_day_offset_dict::DATE_DAY_OFFSET_ITEMS_INIT =
false;
date_day_offset_dict date_day_offset_dict::instance = date_day_offset_dict();
-date_day_offset_dict& date_day_offset_dict::get() {
- return instance;
-}
-
-bool date_day_offset_dict::get_dict_init() {
- return DATE_DAY_OFFSET_ITEMS_INIT;
-}
-
date_day_offset_dict::date_day_offset_dict() {
DateV2Value<DateV2ValueType> d;
// Init days before epoch.
@@ -2813,10 +2805,6 @@ date_day_offset_dict::date_day_offset_dict() {
DATE_DAY_OFFSET_ITEMS_INIT = true;
}
-int date_day_offset_dict::daynr(int year, int month, int day) const {
- return DATE_DAY_OFFSET_DICT[year - START_YEAR][month - 1][day - 1];
-}
-
template <typename T>
uint8_t DateV2Value<T>::week(uint8_t mode) const {
uint16_t year = 0;
@@ -3011,9 +2999,14 @@ bool DateV2Value<T>::date_add_interval(const
TimeInterval& interval) {
return false;
}
if constexpr (is_datetime) {
- PROPAGATE_FALSE(this->check_range_and_set_time(0, 0, 0, seconds /
3600,
- (seconds / 60) %
60, seconds % 60,
- microseconds,
true));
+ if constexpr (need_check) {
+ PROPAGATE_FALSE(this->check_range_and_set_time(0, 0, 0,
seconds / 3600,
+ (seconds / 60)
% 60, seconds % 60,
+ microseconds,
true));
+ } else {
+ this->unchecked_set_time(seconds / 3600, (seconds / 60) % 60,
seconds % 60,
+ microseconds);
+ }
}
} else if constexpr (unit == YEAR) {
// This only change year information
diff --git a/be/src/vec/runtime/vdatetime_value.h
b/be/src/vec/runtime/vdatetime_value.h
index 77df894f21c..f46ce163c11 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -219,6 +219,8 @@ static RE2
time_zone_offset_format_reg(R"(^[+-]{1}\d{2}\:\d{2}$)");
uint8_t mysql_week_mode(uint32_t mode);
+inline uint32_t calc_daynr(uint16_t year, uint8_t month, uint8_t day);
+
struct DateV2ValueType {
uint32_t day_ : 5;
uint32_t month_ : 4;
@@ -1370,7 +1372,7 @@ private:
};
template <typename T>
-inline const DateV2Value<T> DateV2Value<T>::FIRST_DAY = DateV2Value<T>(1, 1,
1, 0, 0, 0, 0);
+inline const DateV2Value<T> DateV2Value<T>::FIRST_DAY = DateV2Value<T>(0001,
1, 1, 0, 0, 0, 0);
// only support DATE - DATE (no support DATETIME - DATETIME)
std::size_t operator-(const VecDateTimeValue& v1, const VecDateTimeValue& v2);
@@ -1613,9 +1615,9 @@ public:
return res >= 0 ? res <= DAY_AFTER_EPOCH : -res <= DAY_BEFORE_EPOCH;
}
- static date_day_offset_dict& get();
+ static date_day_offset_dict& get() { return instance; }
- static bool get_dict_init();
+ static bool get_dict_init() { return DATE_DAY_OFFSET_ITEMS_INIT; }
inline DateV2Value<DateV2ValueType> operator[](int day) const {
int index = day + DAY_BEFORE_EPOCH;
@@ -1627,9 +1629,43 @@ public:
}
}
- int daynr(int year, int month, int day) const;
+ int daynr(int year, int month, int day) const {
+ return DATE_DAY_OFFSET_DICT[year - START_YEAR][month - 1][day - 1];
+ }
};
+inline uint32_t calc_daynr(uint16_t year, uint8_t month, uint8_t day) {
+ // date_day_offet_dict range from [1900-01-01, 2039-12-31]
+ if (date_day_offset_dict::can_speed_up_calc_daynr(year) &&
+ LIKELY(date_day_offset_dict::get_dict_init())) {
+ return date_day_offset_dict::get().daynr(year, month, day);
+ }
+
+ uint32_t delsum = 0;
+ int y = year;
+
+ if (year == 0 && month == 0) {
+ return 0;
+ }
+ if (year == 0 && month == 1 && day == 1) {
+ return 1;
+ }
+
+ /* Cast to int to be able to handle month == 0 */
+ delsum = 365 * y + 31 * (month - 1) + day;
+ if (month <= 2) {
+ // No leap year
+ y--;
+ } else {
+ // This is great!!!
+ // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
+ // 0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 7, 8
+ delsum -= (month * 4 + 23) / 10;
+ }
+ // Every 400 year has 97 leap year, 100, 200, 300 are not leap year.
+ return delsum + y / 4 - y / 100 + y / 400;
+}
+
template <typename T>
struct DateTraits {};
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]