libstdc++: Use std::from_chars to speed up parsing subsecond durations
With std::from_chars we can parse subsecond durations much faster than with std::num_get, as shown in the microbenchmarks below. We were using std::num_get and std::numpunct in order to parse a number with the locale's decimal point character. But we copy the chars from the input stream into a new buffer anyway, so we can replace the locale's decimal point with '.' in that buffer, and then we can use std::from_chars on it. Benchmark Time CPU Iterations ---------------------------------------------------------- from_chars_millisec 158 ns 158 ns 4524046 num_get_millisec 192 ns 192 ns 3644626 from_chars_microsec 164 ns 163 ns 4330627 num_get_microsec 205 ns 205 ns 3413452 from_chars_nanosec 173 ns 173 ns 4072653 num_get_nanosec 227 ns 227 ns 3105161 libstdc++-v3/ChangeLog: * include/bits/chrono_io.h (_Parser::operator()): Use std::from_chars to parse fractional seconds.
This commit is contained in:
parent
5f9d7a5b6c
commit
715127b63d
1 changed files with 18 additions and 10 deletions
|
@ -37,6 +37,7 @@
|
|||
#include <sstream> // ostringstream
|
||||
#include <iomanip> // setw, setfill
|
||||
#include <format>
|
||||
#include <charconv> // from_chars
|
||||
|
||||
#include <bits/streambuf_iterator.h>
|
||||
|
||||
|
@ -3597,13 +3598,17 @@ namespace __detail
|
|||
__err |= ios_base::eofbit;
|
||||
else
|
||||
{
|
||||
auto& __np = use_facet<numpunct<_CharT>>(__loc);
|
||||
auto __dp = __np.decimal_point();
|
||||
_CharT __dp = '.';
|
||||
if (__loc != locale::classic())
|
||||
{
|
||||
auto& __np = use_facet<numpunct<_CharT>>(__loc);
|
||||
__dp = __np.decimal_point();
|
||||
}
|
||||
_CharT __c = _Traits::to_char_type(__i);
|
||||
if (__c == __dp)
|
||||
{
|
||||
(void) __is.get();
|
||||
__buf.put(__c);
|
||||
__buf.put('.');
|
||||
int __prec
|
||||
= hh_mm_ss<_Duration>::fractional_width;
|
||||
do
|
||||
|
@ -3618,14 +3623,17 @@ namespace __detail
|
|||
}
|
||||
}
|
||||
|
||||
if (!__is_failed(__err))
|
||||
if (!__is_failed(__err)) [[likely]]
|
||||
{
|
||||
auto& __ng = use_facet<num_get<_CharT>>(__loc);
|
||||
long double __val;
|
||||
ios_base::iostate __err2{};
|
||||
__ng.get(__buf, {}, __buf, __err2, __val);
|
||||
if (__is_failed(__err2)) [[unlikely]]
|
||||
__err |= __err2;
|
||||
long double __val{};
|
||||
string __str = std::move(__buf).str();
|
||||
auto __first = __str.data();
|
||||
auto __last = __first + __str.size();
|
||||
using enum chars_format;
|
||||
auto [ptr, ec] = std::from_chars(__first, __last,
|
||||
__val, fixed);
|
||||
if ((bool)ec || ptr != __last) [[unlikely]]
|
||||
__err |= ios_base::failbit;
|
||||
else
|
||||
{
|
||||
duration<long double> __fs(__val);
|
||||
|
|
Loading…
Add table
Reference in a new issue