libstdc++: Make chrono::hh_mm_ss more compact
authorJonathan Wakely <jwakely@redhat.com>
Mon, 21 Nov 2022 16:44:50 +0000 (16:44 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 6 Dec 2022 21:38:46 +0000 (21:38 +0000)
commit5329e1a8e1480d536ff96283a6556e51112ba470
treece5e86fbc2101af22c5f64ce05c3ec4ee720abb3
parent4ba94abf147fe7778a7541849ce27cafee74df9b
libstdc++: Make chrono::hh_mm_ss more compact

This uses a single byte for the minutes and seconds members, and places
the bool member next to those single bytes. This means we do not need 40
bytes to store a time that can fit in a single 8-byte integer.

When there is no subsecond precision we can do away with the _M_ss
member altogether. If the subsecond precision is coarse enough, we can
use a smaller representation for _M_ss, e.g. hh_mm_ss<milliseconds> only
needs uint_least32_t for _M_ss, and hh_mm_ss<duration<long, ratio<1,10>>
and hh_mm_ss<duration<int8_t, nano>> only need a single byte. In the
latter case the type can only ever represent up to 255ns anyway, so we
don't need a larger representation type (in such cases, we could even
remove the _M_h, _M_m and _M_s members, but it's a very unlikely
scenario that isn't worth optimizing for).

Except for specializations with a floating-point rep or using higher
precision than nanoseconds, hh_mm_ss should now fit in 16 bytes, or even
12 bytes for x86-32 where alignof(long long) == 4.

libstdc++-v3/ChangeLog:

* include/std/chrono (chrono::hh_mm_ss): Do not use 64-bit
representations for all four duration members. Reorder members.
(hh_mm_ss::hh_mm_ss()): Define as defaulted.
(hh_mm_ss::hh_mm_ss(Duration)): Delegate to a new private
constructor, instead of calling chrono::abs repeatedly.
* testsuite/std/time/hh_mm_ss/1.cc: Check floating-point
representations. Check default constructor. Check sizes.
libstdc++-v3/include/std/chrono
libstdc++-v3/testsuite/std/time/hh_mm_ss/1.cc