diff options
author | Abseil Team <absl-team@google.com> | 2023-02-02 03:05:07 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-02-02 03:05:54 -0800 |
commit | 7005fede1e309d0a6070be3008b365112492aa80 (patch) | |
tree | 99968e37829bea518b344d13e286bd54508aa656 /absl/time/time.h | |
parent | 9858e5421b14c9d72f2103af10010c5452c6d55f (diff) |
Get rid of tail padding within `absl::Duration`. This reduces memory usage needs when storing duration in containers (e.g. `vector<absl::Duration>` uses 25% less memory), and allows classes with `absl::Duration` fields to fit other stuff in memory previously used by tail padding (e.g. `std::optional<absl::Duration>` is now 16 bytes instead of 24).
PiperOrigin-RevId: 506568782
Change-Id: Ic9e077f02a80da013fb2d312aff77761b970c07a
Diffstat (limited to 'absl/time/time.h')
-rw-r--r-- | absl/time/time.h | 73 |
1 files changed, 3 insertions, 70 deletions
diff --git a/absl/time/time.h b/absl/time/time.h index bf1007c2..cc390082 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -84,7 +84,6 @@ struct timeval; #include <type_traits> #include <utility> -#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "absl/time/civil_time.h" @@ -215,7 +214,7 @@ class Duration { template <typename H> friend H AbslHashValue(H h, Duration d) { - return H::combine(std::move(h), d.rep_hi_.Get(), d.rep_lo_); + return H::combine(std::move(h), d.rep_hi_, d.rep_lo_); } private: @@ -224,73 +223,7 @@ class Duration { friend constexpr Duration time_internal::MakeDuration(int64_t hi, uint32_t lo); constexpr Duration(int64_t hi, uint32_t lo) : rep_hi_(hi), rep_lo_(lo) {} - - // We store `hi_rep_` 4-byte rather than 8-byte aligned to avoid 4 bytes of - // tail padding. - class HiRep { - public: - // Default constructor default-initializes `hi_`, which has the same - // semantics as default-initializing an `int64_t` (undetermined value). - HiRep() = default; - - HiRep(const HiRep&) = default; - HiRep& operator=(const HiRep&) = default; - - explicit constexpr HiRep(const int64_t value) - : // C++17 forbids default-initialization in constexpr contexts. We can - // remove this in C++20. - lo_(0), - hi_(0) { - *this = value; - } - - constexpr int64_t Get() const { - const uint64_t unsigned_value = - (static_cast<uint64_t>(hi_) << 32) | static_cast<uint64_t>(lo_); - // `static_cast<int64_t>(unsigned_value)` is implementation-defined - // before c++20. On all supported platforms the behaviour is that mandated - // by c++20, i.e. "If the destination type is signed, [...] the result is - // the unique value of the destination type equal to the source value - // modulo 2^n, where n is the number of bits used to represent the - // destination type." - static_assert( - (static_cast<int64_t>((std::numeric_limits<uint64_t>::max)()) == - int64_t{-1}) && - (static_cast<int64_t>(static_cast<uint64_t>( - (std::numeric_limits<int64_t>::max)()) + - 1) == - (std::numeric_limits<int64_t>::min)()), - "static_cast<int64_t>(uint64_t) does not have c++20 semantics"); - return static_cast<int64_t>(unsigned_value); - } - - constexpr HiRep& operator=(const int64_t value) { - // "If the destination type is unsigned, the resulting value is the - // smallest unsigned value equal to the source value modulo 2^n - // where `n` is the number of bits used to represent the destination - // type". - const auto unsigned_value = static_cast<uint64_t>(value); - hi_ = static_cast<uint32_t>(unsigned_value >> 32); - lo_ = static_cast<uint32_t>(unsigned_value); - return *this; - } - - private: - // Notes: - // - Ideally we would use a `char[]` and `std::bitcast`, but the latter - // does not exist (and is not constexpr in `absl`) before c++20. - // - Order is optimized depending on endianness so that the compiler can - // turn `Get()` (resp. `operator=()`) into a single 8-byte load (resp. - // store). -#if defined(ABSL_IS_BIG_ENDIAN) && ABSL_IS_BIG_ENDIAN - uint32_t hi_; - uint32_t lo_; -#else - uint32_t lo_; - uint32_t hi_; -#endif - }; - HiRep rep_hi_; + int64_t rep_hi_; uint32_t rep_lo_; }; @@ -1558,7 +1491,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeNormalizedDuration( // Provide access to the Duration representation. ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d) { - return d.rep_hi_.Get(); + return d.rep_hi_; } ABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; |