From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: [committed] libstdc++: Use std::from_chars to speed up parsing subsecond durations
Date: Fri, 8 Mar 2024 00:10:00 +0000 [thread overview]
Message-ID: <20240308001015.684795-1-jwakely@redhat.com> (raw)
Tested x86_64-linux. Pushed to trunk.
-- >8 --
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.
---
libstdc++-v3/include/bits/chrono_io.h | 28 +++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index b8f0657bee9..412e8b83fb7 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -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);
--
2.43.2
reply other threads:[~2024-03-08 0:10 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240308001015.684795-1-jwakely@redhat.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).