diff options
author | Abseil Team <absl-team@google.com> | 2024-02-27 04:34:27 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-02-27 04:35:39 -0800 |
commit | bde089f91c7da54aea5b3694c6ce58cb020e06fe (patch) | |
tree | e8f71b4ef0794f1ddc80b64c1d96567e71a09351 /absl/time/time.h | |
parent | 90ebb6fca0932e33f278d31d42101bb242b7dc7c (diff) | |
download | abseil-bde089f91c7da54aea5b3694c6ce58cb020e06fe.tar.gz abseil-bde089f91c7da54aea5b3694c6ce58cb020e06fe.tar.bz2 abseil-bde089f91c7da54aea5b3694c6ce58cb020e06fe.zip |
Optimize `absl::Duration` division and modulo: Allow the compiler to inline `time_internal::IDivDuration`, by splitting the slow path to a separate function.
With that change, the compiler can inline the fast path. This is specially important in the context of `Duration::operator%=`, because it allows proving that the return value is unused, therefore avoiding expensive multiplies and divides (e.g. `*q = num_hi / den_hi;`).
```
name old cpu/op new cpu/op delta
BM_Duration_Modulo 23.1ns ± 0% 22.5ns ± 0% -2.42% (p=0.000 n=20+16)
BM_Duration_Modulo_FastPath 7.05ns ± 0% 4.85ns ± 0% -31.17% (p=0.000 n=20+20)
name old time/op new time/op delta
BM_Duration_Modulo 23.1ns ± 0% 22.6ns ± 0% -2.43% (p=0.000 n=20+16)
BM_Duration_Modulo_FastPath 7.06ns ± 0% 4.86ns ± 0% -31.18% (p=0.000 n=20+20)
name old INSTRUCTIONS/op new INSTRUCTIONS/op delta
BM_Duration_Modulo 188 ± 0% 178 ± 0% -5.32% (p=0.000 n=20+20)
BM_Duration_Modulo_FastPath 84.0 ± 0% 62.0 ± 0% -26.19% (p=0.000 n=20+20)
name old CYCLES/op new CYCLES/op delta
BM_Duration_Modulo 73.8 ± 0% 72.1 ± 0% -2.27% (p=0.000 n=19+20)
BM_Duration_Modulo_FastPath 22.5 ± 0% 15.5 ± 0% -31.13% (p=0.000 n=19+20)
```
Note: We don't need to expose `absl::time_internal::IDivDuration` at all given that we have a public `absl::IDivDuration`.
PiperOrigin-RevId: 610710635
Change-Id: Ief7c3d5b1c000b397d931e9249edcaef96e7151e
Diffstat (limited to 'absl/time/time.h')
-rw-r--r-- | absl/time/time.h | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/absl/time/time.h b/absl/time/time.h index 37580805..d367ace2 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -98,7 +98,6 @@ class Time; // Defined below class TimeZone; // Defined below namespace time_internal { -int64_t IDivDuration(bool satq, Duration num, Duration den, Duration* rem); ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d); ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t); ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d); @@ -338,30 +337,6 @@ ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Duration lhs, return lhs -= rhs; } -// Multiplicative Operators -// Integer operands must be representable as int64_t. -template <typename T> -ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(Duration lhs, T rhs) { - return lhs *= rhs; -} -template <typename T> -ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(T lhs, Duration rhs) { - return rhs *= lhs; -} -template <typename T> -ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator/(Duration lhs, T rhs) { - return lhs /= rhs; -} -ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t operator/(Duration lhs, - Duration rhs) { - return time_internal::IDivDuration(true, lhs, rhs, - &lhs); // trunc towards zero -} -ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator%(Duration lhs, - Duration rhs) { - return lhs %= rhs; -} - // IDivDuration() // // Divides a numerator `Duration` by a denominator `Duration`, returning the @@ -390,10 +365,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator%(Duration lhs, // // Here, q would overflow int64_t, so rem accounts for the difference. // int64_t q = absl::IDivDuration(a, b, &rem); // // q == std::numeric_limits<int64_t>::max(), rem == a - b * q -inline int64_t IDivDuration(Duration num, Duration den, Duration* rem) { - return time_internal::IDivDuration(true, num, den, - rem); // trunc towards zero -} +int64_t IDivDuration(Duration num, Duration den, Duration* rem); // FDivDuration() // @@ -409,6 +381,30 @@ inline int64_t IDivDuration(Duration num, Duration den, Duration* rem) { // // d == 1.5 ABSL_ATTRIBUTE_CONST_FUNCTION double FDivDuration(Duration num, Duration den); +// Multiplicative Operators +// Integer operands must be representable as int64_t. +template <typename T> +ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(Duration lhs, T rhs) { + return lhs *= rhs; +} +template <typename T> +ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(T lhs, Duration rhs) { + return rhs *= lhs; +} +template <typename T> +ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator/(Duration lhs, T rhs) { + return lhs /= rhs; +} +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t operator/(Duration lhs, + Duration rhs) { + return IDivDuration(lhs, rhs, + &lhs); // trunc towards zero +} +ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator%(Duration lhs, + Duration rhs) { + return lhs %= rhs; +} + // ZeroDuration() // // Returns a zero-length duration. This function behaves just like the default |