public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/110801] New: std::format code runs slower than equivalent {fmt} code
@ 2023-07-25 10:58 redi at gcc dot gnu.org
2023-08-15 21:42 ` [Bug libstdc++/110801] " redi at gcc dot gnu.org
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: redi at gcc dot gnu.org @ 2023-07-25 10:58 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110801
Bug ID: 110801
Summary: std::format code runs slower than equivalent {fmt}
code
Product: gcc
Version: 13.1.1
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
Using the benchmark from
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0645r10.html#Benchmarks
and adding:
#if __has_include(<format>)
#include <format>
#endif
#ifdef __cpp_lib_format
void std_format(benchmark::State& s) {
size_t result = 0;
while (s.KeepRunning()) {
for (auto i: data)
result += std::format("{}", i).size();
}
benchmark::DoNotOptimize(result);
}
BENCHMARK(std_format);
void std_format_to(benchmark::State& s) {
size_t result = 0;
while (s.KeepRunning()) {
for (auto i: data) {
char buffer[12];
result += std::format_to(buffer, "{}", i) - buffer;
}
}
benchmark::DoNotOptimize(result);
}
BENCHMARK(std_format_to);
#endif
I get:
Benchmark Time CPU Iterations
--------------------------------------------------------
sprintf 708600 ns 706474 ns 946
ostringstream 1216025 ns 1210087 ns 589
to_string 178579 ns 178088 ns 3824
format 306344 ns 305365 ns 2345
format_to 145606 ns 145223 ns 4940
std_format 514969 ns 513563 ns 1376
std_format_to 436502 ns 435402 ns 1567
The std::to_string performance is good, but std::format is much slower than
fmt::format.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug libstdc++/110801] std::format code runs slower than equivalent {fmt} code
2023-07-25 10:58 [Bug libstdc++/110801] New: std::format code runs slower than equivalent {fmt} code redi at gcc dot gnu.org
@ 2023-08-15 21:42 ` redi at gcc dot gnu.org
2023-08-17 17:26 ` redi at gcc dot gnu.org
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: redi at gcc dot gnu.org @ 2023-08-15 21:42 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110801
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Created attachment 55739
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55739&action=edit
Add special case for format("{}", integer)
With this patch std::format is much closer to fmt::format:
Benchmark Time CPU Iterations
--------------------------------------------------------
sprintf 554621 ns 553889 ns 1241
ostringstream 932465 ns 931258 ns 746
to_string 122602 ns 122425 ns 5424
format 241978 ns 241656 ns 2939
format_to 109541 ns 109391 ns 6282
std_format 282151 ns 281787 ns 2490
std_format_to 225596 ns 225301 ns 3080
std::format_to could still be faster. It should be potentially as fast as
to_string.
The patch is just a prototype that only optimizes for integers, but the idea
could be extended to other types too. For integers, floats, strings, and
pointers we can skip the formatter::parse and formatter::format calls for a
"{}" format string and just do the basic output form, with none of the
additional code for alternative presentation forms, alignment, width, precision
etc.
As well as short-circuiting most of the formatting logic, the other part of the
optimization is writing directly to the output buffer if it is a contiguous
iterator (or a sink iterator that writes to a contiguous container). This is
more efficient than writing to a buffer and then copying to the output. This
could be extended to work with a back_insert_iterator<string> or
back_insert_iterator<vector>, as we could extract the container, resize it, and
then write directly into it.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug libstdc++/110801] std::format code runs slower than equivalent {fmt} code
2023-07-25 10:58 [Bug libstdc++/110801] New: std::format code runs slower than equivalent {fmt} code redi at gcc dot gnu.org
2023-08-15 21:42 ` [Bug libstdc++/110801] " redi at gcc dot gnu.org
@ 2023-08-17 17:26 ` redi at gcc dot gnu.org
2023-11-18 21:44 ` cvs-commit at gcc dot gnu.org
2023-11-18 21:51 ` redi at gcc dot gnu.org
3 siblings, 0 replies; 5+ messages in thread
From: redi at gcc dot gnu.org @ 2023-08-17 17:26 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110801
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #1)
> Created attachment 55739 [details]
> Add special case for format("{}", integer)
The _Seq_sink::_M_get_pointer and _Iter_sink::_M_get_pointer overrides in this
patch are broken. They assume that no other output has already been done to the
sink, but that isn't true if you have a formatter that writes some output then
uses format("{}", i) to write some more (e.g. chrono formatters). The
format("{}", i) call will use the new fast path and call _M_get_pointer which
currently gives a pointer to the start of the buffer, but that overwrites
anything already written there.
I have a fix for that.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug libstdc++/110801] std::format code runs slower than equivalent {fmt} code
2023-07-25 10:58 [Bug libstdc++/110801] New: std::format code runs slower than equivalent {fmt} code redi at gcc dot gnu.org
2023-08-15 21:42 ` [Bug libstdc++/110801] " redi at gcc dot gnu.org
2023-08-17 17:26 ` redi at gcc dot gnu.org
@ 2023-11-18 21:44 ` cvs-commit at gcc dot gnu.org
2023-11-18 21:51 ` redi at gcc dot gnu.org
3 siblings, 0 replies; 5+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2023-11-18 21:44 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110801
--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:
https://gcc.gnu.org/g:41a5ea4cab2c59f9911325281f7df1d3ae846d48
commit r14-5587-g41a5ea4cab2c59f9911325281f7df1d3ae846d48
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Aug 15 22:43:41 2023 +0100
libstdc++: Add fast path for std::format("{}", x) [PR110801]
This optimizes the simple case of formatting a single string, integer
or bool, with no format-specifier (so no padding, alignment, alternate
form etc.)
libstdc++-v3/ChangeLog:
PR libstdc++/110801
* include/std/format (_Sink_iter::_M_reserve): New member
function.
(_Sink::_Reservation): New nested class.
(_Sink::_M_reserve, _Sink::_M_bump): New virtual functions.
(_Seq_sink::_M_reserve, _Seq_sink::_M_bump): New virtual
overrides.
(_Iter_sink<O, ContigIter>::_M_reserve): Likewise.
(__do_vformat_to): Use new functions to optimize "{}" case.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug libstdc++/110801] std::format code runs slower than equivalent {fmt} code
2023-07-25 10:58 [Bug libstdc++/110801] New: std::format code runs slower than equivalent {fmt} code redi at gcc dot gnu.org
` (2 preceding siblings ...)
2023-11-18 21:44 ` cvs-commit at gcc dot gnu.org
@ 2023-11-18 21:51 ` redi at gcc dot gnu.org
3 siblings, 0 replies; 5+ messages in thread
From: redi at gcc dot gnu.org @ 2023-11-18 21:51 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110801
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Last reconfirmed| |2023-11-18
Ever confirmed|0 |1
--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I get these numbers now:
sprintf 530172 ns 529123 ns 1366
ostringstream 1150474 ns 1147048 ns 613
to_string 150262 ns 149901 ns 4680
format 284007 ns 283124 ns 2481
format_to 142947 ns 142612 ns 5046
std_format 340518 ns 339737 ns 2062
std_format_to 296434 ns 295710 ns 2407
There's still room for improvement.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-11-18 21:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-25 10:58 [Bug libstdc++/110801] New: std::format code runs slower than equivalent {fmt} code redi at gcc dot gnu.org
2023-08-15 21:42 ` [Bug libstdc++/110801] " redi at gcc dot gnu.org
2023-08-17 17:26 ` redi at gcc dot gnu.org
2023-11-18 21:44 ` cvs-commit at gcc dot gnu.org
2023-11-18 21:51 ` redi at gcc dot gnu.org
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).