Topic: iostream
Author: Vesa A J Karvonen <vkarvone@cc.helsinki.fi>
Date: 1999/10/10 Raw View
Siemel B. Naran <sbnaran@uiuc.edu> wrote:
> On 8 Oct 1999 15:34:58 GMT, Vesa A J Karvonen <vkarvone@cc.helsinki.fi> wrote:
[snip]
> What do you mean by "delegate to a set of virtual functions in the same
> object"?
["delegate" isn't perhaps the best word to describe the mechanism.]
In particular, the design employed by streambufs:
template<...>
class basic_streambuf {
public:
// ...
int pubsync();
streamsize in_avail();
int_type snextc();
int_type sbumpc();
int_type sgetc();
streamsize sgetn(E *s, streamsize n);
int_type sputbackc(E c);
int_type sungetc();
int_type sputc(E c);
streamsize sputn(const E *s, streamsize n);
protected:
// ...
virtual int sync();
virtual int showmanyc();
virtual streamsize xsgetn(E *s, streamsize n);
virtual int_type underflow();
virtual int_type uflow();
virtual int_type pbackfail(int_type c = T::eof());
virtual streamsize xsputn(const E *s, streamsize n);
virtual int_type overflow(int_type c = T::eof());
};
Most of the public inline functions first try to use the embedded buffer
and then call the virtual functions. In some cases, the public function
does nothing but call the protected virtual function. In most cases, the
public functions are implemented as inline functions. Like I said, I
think that this has many problems (with performance and flexibility),
which can be solved by using a pure virtual interface and the Decorator
pattern.
If you want to discuss this C++ design pattern in more detail, I think
some other newsgroup like news:comp.lang.c++.moderated would be more
appropriate. If you want to continue on iostreams, I'd suggest that we'd
design and implement an alternative stream architecture, and test it
against as many standard stream implementations as possible. I think
that we could spend days throwing around opinnions on what is good and
what isn't. Standard streams are for anyone to see, but the alternative
designs aren't. If we could get some concrete designs and numbers to
show, it might help to evaluate the problems and advantages of the
current standard streams. According to my experiments, there is a lot of
room for both performance and flexibility improvements.
---
Vesa Karvonen
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Matt Austern <austern@sgi.com>
Date: 1999/10/10 Raw View
sbnaran@uiuc.edu (Siemel B. Naran) writes:
> On 8 Oct 1999 15:34:58 GMT, Vesa A J Karvonen <vkarvone@cc.helsinki.fi> wrote:
>
> >The standard stream architecture, which uses, IMHO, the poor C++ idiom
> >of using a set of non-virtual inline functions that delegate to a set of
> >virtual functions *in the same object* (see The C++ Programming
> >Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
> >significantly less flexible and also somewhat less efficient. The
> >standard streams also suffer badly from other kinds of added
> >responsibilities that could be implemented more flexibly and efficiently
> >using the Decorator pattern. Based on my tests, the added
> >responsibilities of both basic_streambuf and basic_istream result in a
> >slowdown (reciprocal of speedup) of about a factor of 2-20 depending on
> >the amount of data trasferred per transaction.
>
> What do you mean by "delegate to a set of virtual functions in the same
> object"?
Just that. For example, std::basic_streambuf<> has a public,
nonvirtual member function pubseekoff that is documented
(27.5.2.2.2/2) just to turn around and invoke the protected,
virtual member function seekoff.
There are reasonable arguments both for and against this practice, but
I don't think that efficiency is one. If pubseekoff really is just a
one-line function that invokes seekoff, a good compiler should have no
trouble inlining it away.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Vesa A J Karvonen <vkarvone@cc.helsinki.fi>
Date: 1999/10/11 Raw View
Matt Austern <austern@sgi.com> wrote:
[snip]
> There are reasonable arguments both for and against this practice, but
> I don't think that efficiency is one. If pubseekoff really is just a
> one-line function that invokes seekoff, a good compiler should have no
> trouble inlining it away.
[snip]
The problem isn't pubseekoff() or pubsync(), etc... Although with some
compilers, the virtual call does not get optimized away (perhaps the
compiler forgets that it knows the most derived type of the object when
it "enters" the inline function), even if the compiler can do it when
you call an inline virtual function. Anyway, most of those functions
aren't even called often enough that you should even need to optimize
them.
The problem is with sbumbc(), sputbackc(), sputc(), atc... Those
functions perform buffering before reverting to the virtual stuff. If
you don't have buffering, you'll pay an extra cost for the redundant
conditionals. For simple single character operations, the overhead of
the redundant conditional can double the time of the operation. With the
Decorator approach, you will not have *any* redundant conditionals for
buffering and the speed-up is significant.
However, in practise, no-one uses streambufs directly. Instead, the
istream/ostream interface is used for IO. The combined overhead of both
istream and streambuf is staggering! [I think I'll have to dig up the
tests someday and put them on the web for everyone to see.]
---
Vesa Karvonen
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/10/10 Raw View
On 8 Oct 1999 15:34:58 GMT, Vesa A J Karvonen <vkarvone@cc.helsinki.fi> wrote:
>The standard stream architecture, which uses, IMHO, the poor C++ idiom
>of using a set of non-virtual inline functions that delegate to a set of
>virtual functions *in the same object* (see The C++ Programming
>Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
>significantly less flexible and also somewhat less efficient. The
>standard streams also suffer badly from other kinds of added
>responsibilities that could be implemented more flexibly and efficiently
>using the Decorator pattern. Based on my tests, the added
>responsibilities of both basic_streambuf and basic_istream result in a
>slowdown (reciprocal of speedup) of about a factor of 2-20 depending on
>the amount of data trasferred per transaction.
What do you mean by "delegate to a set of virtual functions in the same
object"?
--
--------------
siemel b naran
--------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]