Re: [PATCH 4/4] libstdc++: Optimize std::print using _Streambuf_sink

Tomasz Kaminski <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel
Message-ID <CAKvuMXB7=DD5GO9A75Xf6iNiKR-oxfOE2g7-W8Npiyict+6R9w@mail.gmail.com>
On Thu, Jul 16, 2026 at 2:05 PM Anlai Lu <[email protected]> wrote:

> Use _Streambuf_sink directly in vprint_nonunicode instead of
> formatting to an intermediate string (_Str_sink) and then writing
> it to the stream.  This avoids the temporary string allocation and
> extra copy, and allows zero-copy writes into the streambuf's put
> area.
>
> I/O errors are tracked internally by _Streambuf_sink and reported
> after formatting completes via setstate(badbit), so that exceptions
> from vformat (format_error, bad_alloc) propagate without setting
> badbit, meeting [ostream.formatted.print]/(4.2).
>
Unfortunately, I have  realized that this is non-conforming, as it's
leads to differences in observable behavior, for example in the following
two cases: print(os, "{} {}", t, u)
- if t is formatted successfully but formatting
   of u throws, then standard requires no changes (we haven't created a
  string to print), but _Stream_sink may write representation of t
- if formatter of t or u prints to os direclty, the standard is clear that
  we get the direct output from formatters and then the result of the
format,
  but we may interleave
I will post updated patch 1/4 that adds above example./

I think this optimization is worthwhile, and maybe we could reuse
existing enable_nonlocking_formatter_optimziation to print direclty to
ostream (we require opt-in). But that requires changes to the standard.

Would be interested in working on standard proposal on such effect?


>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/ostream_print.h (vprint_nonunicode): Use
>         _Streambuf_sink instead of _Str_sink + __ostream_write.
>
> Signed-off-by: Anlai Lu <[email protected]>
> ---
>  libstdc++-v3/include/bits/ostream_print.h | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/ostream_print.h
> b/libstdc++-v3/include/bits/ostream_print.h
> index 0adf16d4f..4542bfcbf 100644
> --- a/libstdc++-v3/include/bits/ostream_print.h
> +++ b/libstdc++-v3/include/bits/ostream_print.h
> @@ -61,21 +61,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      ostream::sentry __cerb(__os);
>      if (__cerb)
>        {
> -       __format::_Str_sink<char> __buf;
> -       std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
> -       auto __out = __buf.view();
> -
> +       __format::_Streambuf_sink<char> __sink(__os.rdbuf());
>         __try
>           {
> -           std::__ostream_write(__os, __out.data(), __out.size());
> +           std::vformat_to(__sink.out(), __os.getloc(), __fmt, __args);
> +           std::move(__sink)._M_finish();
>           }
>         __catch(const __cxxabiv1::__forced_unwind&)
>           {
>             __os._M_setstate(ios_base::badbit);
>             __throw_exception_again;
>           }
> -       __catch(...)
> -         { __os._M_setstate(ios_base::badbit); }
> +       if (__sink._M_failed())
> +         __os.setstate(ios_base::badbit);
>        }
>    }
>
> --
> 2.34.1
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.