This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: libstdc++/3269: Inefficient stream output, one 'write' call per character
- To: Benjamin Kosnik <bkoz at redhat dot com>
- Subject: Re: libstdc++/3269: Inefficient stream output, one 'write' call per character
- From: Carlo Wood <carlo at alinoe dot com>
- Date: Wed, 27 Jun 2001 03:27:10 +0200
- Cc: Anders Furuhed <anders dot furuhed at pantor dot com>, gcc-bugs at gcc dot gnu dot org, gcc-prs at gcc dot gnu dot org, nobody at gcc dot gnu dot org
- References: <20010627022510.A20861@alinoe.com> <Pine.SOL.3.91.1010626173133.18624A-100000@taarna.cygnus.com>
On Tue, Jun 26, 2001 at 05:32:17PM -0700, Benjamin Kosnik wrote:
>
> Thanks Carlo. I don't suppose you have an example, or some code that
> would demonstrate this? I'm a bit confused as to what you are suggesting.
>
> -benjamin
I was assuming that overflow was called from somewhere else than xsputn(), and
was mistaken. Nevertheless, there must be a solution; so lets look at what
happens exactly:
std::cout << "Hello World\n";
calls
ostream& std::operator<<(ostream&, char const*)
which in turn calls
ostream::write(char const*, int)
this then calls
rdbuf()->sputn(__s, __n);
which is
streambuf::sputn(char const*, int)
this simply calls the virtual function
this->xsputn(__s, __n);
which is
filebuf::xsputn(char const*, int)
which does nothing special, but simply calls
streambuf::xsputn(char const*, int)
This function detects that it (the streambuf) doesn't have any buffer, and calls
the virtual function 'overflow', making us end up here:
filebuf::overflow(int)
which in turn calls
filebuf::_M_really_overflow(int)
which in turn calls
_M_file->xsputn(&__pending, 1);
which then finally calls
std::__basic_file<char>::xsputn(char const*, int)
which calls fwrite() directly, writing a single character.
The solution (if any) seems to be to detect that there is no buffer in filebuf::xsputn
and instead of calling streambuf::xsputn, directly calling _M_file->xsputn using larger
chunks of data.
At the moment, filebuf::xsputn is defined as
virtual streamsize
xsputn(const char_type* __s, streamsize __n)
{
_M_pback_destroy();
return __streambuf_type::xsputn(__s, __n);
}
Simply replacing __streambuf_type::xsputn by _M_file->xsputn is wrong (apart from that
not all data is garanteed to be written in one call) because then we'd skip the locale
translation. My guess therefore is that a temporal buffer of some size would be needed
to do this translation - and only then a call to write(2) is possible. I am not into this
locale stuff at all and would have to dig into streambuf::xsputn, filebuf::overflow and
filebuf::_M_really_overflow in greater detail before being able to give example code
that would mimic their behaviour but do only one call to _M_file->xsputn per (say) 512
characters instead of one per character.
Hopefully this clarifies what I really tried to say. I leave it entirely to others to
decide if this is worth it - and last but not least if this wouldn't break some part
of the standard.
--
Carlo Wood <carlo@alinoe.com>