This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: libstdc++/3269: Inefficient stream output, one 'write' call per character


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>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]