Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

printf vs streams (cout) - performance vs robustness?

2,671 views
Skip to first unread message

Diego Martins

unread,
Jul 30, 2008, 2:58:19 PM7/30/08
to
Sometimes, I find code where the developers prefer to use printf/
fprintf, instead of ostream classes. They claim:
a) performance reasons
b) the ability of quickly replacing the format string

for security reasons, I want to get rid of type-unsafe printf
philosophy. so I have some questions lying around:

- is printf really faster than streams in most of cases? where can I
find more info about that?

- b) is a very strong issue! for example, format strings allows
reording of the arguments (their order is hardcoded using streams).
this ease the application deployment. is there a good workaround with
streams?

Diego
HP

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Thomas Richter

unread,
Jul 30, 2008, 6:34:21 PM7/30/08
to
Diego Martins wrote:
> Sometimes, I find code where the developers prefer to use printf/
> fprintf, instead of ostream classes. They claim:
> a) performance reasons
> b) the ability of quickly replacing the format string
>
> for security reasons, I want to get rid of type-unsafe printf
> philosophy.

Note that most modern compilers will check the arguments for you if they
can, i.e. if the format string is available for them.

> so I have some questions lying around:
>
> - is printf really faster than streams in most of cases? where can I
> find more info about that?

I doubt that this is a reasonable argument. printf() and streams should
be I/O bound, I would guess that the execution time of the call itself
is irrelevant compared to the time to do the I/O (e.g. make the letters
appear on the console).

So long,
Thomas

Oncaphillis

unread,
Jul 30, 2008, 6:37:24 PM7/30/08
to
Diego Martins wrote:
> - is printf really faster than streams in most of cases? where can I
> find more info about that?

I assume this is asking for a flame war, where people claim
that their implementation of vendor X on platform Y is much more
performant with (iostream|printf). The most generic answer I could
give is that it is implementation dependent, but I don't see any particular
performance bottleneck in either of them.

(a) Both systems have to format the output somehow, (b) manage
an internal file/stream buffer and (c) pump out the result into a file
handle which in both of the cases is done via (f|)write I assume.
And at that point it is the operating systems responsibility
to do it as efficiently as possible.

The only performance penalty I see is that printf has to parse the
format string, while the current output format (setprecision, hex,
dec etc.) is stored within the iostream in a more appropriate way
for the CPU to understand. But may be there are even optimizations
available for the parsing step.

> - b) is a very strong issue! for example, format strings allows
> reording of the arguments (their order is hardcoded using streams).
> this ease the application deployment. is there a good workaround with
> streams?

Hmm -- I'm not sure if I understand that point. You can not *reorder*
the arguments for printf matching values always have to appear in the
order given within the format string. You might change the format
dynamically via:

<snip>
int foo(int i,int n) {
const char * str1 "%x:%s\n";
const char * str2 "%d:%s\n";
if (i==0) {
printf(str1,n,"hello");
else {
printf(str2,n,"hello");
}
}
</snip>

So dependent on the argument i n will be printed as a hex value
or a dec value. But you're not allowed to change the order of %x
and %s.

Or wait -- yes you *are* allowed to change the order without any
penalty of the great god of C-Programming, but then your
program dumps out junk or even crashes trying to interpret an
integer as a string address, and that AFAICT is the main reason that
(f|)printf is said to be *evil*. You have a couple of arguments which
are semantically linked (the %d and the n in the example above)
but printf does not force you to respect this semantics. It's
just a string and an integer.

With the -Wall flag gcc warns me that I'm doing he wrong thing
when trying this:

<snip>
printf("%s",10);
</snip>

But I think that's just pure luxury and not part of the standard.
And it fails if I provide the format string as a variable.

Another thing speaking for iostreams is the fact, that
it can be much more then just a file/terminal. You may
build up a whole collection of classes/functions/operators
working on a std::basic_ostream<CharT,...> & and
work on std::cout for months and afterwards you write
your own sublass of basic_ostream<...> and the output
ends up in a window, a database or as an output
stream of a web application.

So now you know why everyone using printf will
burn in hell ;-)

O.

ppi

unread,
Jul 30, 2008, 6:58:19 PM7/30/08
to
> - is printf really faster than streams in most of cases? where can I
> find more info about that?

The only issue I had with iostreams - related to performances - was
when I forgot to call sync_with_stdio( false ) on my C++ streams and
suffered a penalty hit (do not know if this still stands today) using
some vendor lib. I do not see why c++ streams would be slower than c
streams: I/O are very slow operations per se.

-- paulo

Oncaphillis

unread,
Jul 31, 2008, 12:28:20 AM7/31/08
to
Oncaphillis wrote:

>> - b) is a very strong issue! for example, format strings allows
>> reording of the arguments (their order is hardcoded using streams).
>> this ease the application deployment. is there a good workaround with
>> streams?
>
> Hmm -- I'm not sure if I understand that point. You can not *reorder*
> the arguments for printf matching values always have to appear in the
> order given within the format string. You might change the format
> dynamically via:
>

guess now i understand what you mean. the ability to have your
values printed within different strings e.g. for internationalization.
that's a big issue and if for example you look at the effort libraries
like Qt take in QString::args I think there really isn't an easy solution.
and (f|)printf doesn't help you much since different languages need
different ordering for their args. That's the reason such libraries
use placeholders like '%1'...'%5' in their format string instead
of '%d' '%s'. And they come up with things like this:

<snip>
QString("Processing file %1 of %2: %3").arg(i).arg(total).arg(fileName);
</snip>

...which isn't really beautiful AFAICS

Hope I understood your point

Tony Delroy

unread,
Jul 31, 2008, 12:28:21 AM7/31/08
to
On Jul 31, 3:58 am, Diego Martins <jose.di...@gmail.com> wrote:
> - is printf really faster than streams in most of cases? where can I
> find more info about that?
>
> - [snip] format strings allow
> reordering of the arguments (their order is hardcoded using streams).

> this ease the application deployment. is there a good workaround with
> streams?

My impression is that many early streams implementations got to the
stage where they knew the precision and width and needed to put it
into the stream, so they used an sprintf("%*.*lf", ...) call to
prepare the data, hence ensuring real numbers rendered slower. I
sincerely hope modern streams implementations have at least ripped off
the *printf() implementation to inline it, and hopefully optimised it
a bit in the process. In general, streams have the advantage of
knowing the types at compile time, so can be faster.

Re convenience and re-ordering, only certain printf() implementations
(e.g. GNU) allow reordering. Perhaps you should look at the boost
formatting library, which uses printf()-style format strings but has
benefits.

Also, only certain printf() implementations allow you to supplement
the conversion specifiers (e.g. GNU). It's not portable. Whereas,
you can easily write a operator<< for your user-defined type. This is
a core reason to use streams: the type of a variable can be changed to
some customised type and the input/output code typically works
unchanged. Having to modify "%d", x to "%s", x.str() everywhere is
tedious. I'm a firm believer that almost every class should be
streamable too... very useful for test cases, debug trace, etc..

Cheers,

Tony

Seungbeom Kim

unread,
Jul 31, 2008, 7:19:53 AM7/31/08
to
Diego Martins wrote:
> Sometimes, I find code where the developers prefer to use printf/
> fprintf, instead of ostream classes. They claim:
> a) performance reasons
> b) the ability of quickly replacing the format string

My major complaints about the iostream library are:

1. It's tedious and verbose to set the formatting flags: compare
(a) printf("%6.4f", x);
vs
(b1) std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
std::cout.precision(4);
std::cout.width(6);
std::cout << x;
or (with <iomanip>)
(b2) std::cout << std::fixed << std::setprecision(4) << std::setw(6)
<< x;
(not counting restoration of the flags)

2. Formatting flags are persistent, so writing a I/O subroutine often
involves saving the formatting flags at the beginning and restoring
them at the end.

These two problems can be largely solved by helper classes that save
the formatting flags at construction, set them as specified by the
client, do the I/O, and restore the flags at destruction. It's not
very hard to write one, and I also have done that. However:

1. They're not standardized, so everyone's inventing their own wheel,
and it's a waste of time both to write them individually and to
understand each other's. (Anything coming in C++0x?)

2. Saving and restoring formatting flags are often wasteful, because
you'll be setting another flag after restoring them anyway. Suppose
you're printing a table, where each column has its own format [a very
common situation]. The sequence of formatting flags set on the stream
will be A->B->A->C->A->D->A..., when what you really need is just
A->B->C->D->.... It may not be that expensive (especially compared
to the actual I/O cost), and compilers really good at optimization
could get away with even that, but I doubt such are very common,
and it makes me uncomfortable anyway. (I may be paranoid...)

I haven't seen the rationale behind the decision to make the flags
persistent, but I suspect that it was caused by the limitation of the
binary inserter/extractor syntax, the inability to supply formatting
specification together with the data, and I wish there had been a
better way to solve it. Persistence of formatting flags have caused
me more pain than benefit, unfortunately.

I know there are solutions such as Boost.Format, but I doubt if
that's just an extra layer of abstraction, adding the cost of parsing
the format string while not eliminating the cost of manipulating
the formatting flags (and of course the virtual function call).

--
Seungbeom Kim

Seungbeom Kim

unread,
Jul 31, 2008, 7:17:56 AM7/31/08
to
ppi wrote:
>> - is printf really faster than streams in most of cases? where can I
>> find more info about that?
>
> The only issue I had with iostreams - related to performances - was
> when I forgot to call sync_with_stdio( false ) on my C++ streams and
> suffered a penalty hit (do not know if this still stands today) using
> some vendor lib. I do not see why c++ streams would be slower than c
> streams: I/O are very slow operations per se.

I suspect that a significant portion of C++ programs do not bother to
call sync_with_stdio(false), while not mixing stdio and iostream at all.
I wonder, doesn't this violate the zero-overhead rule? Someone can
argue: if programs are not using the feature of mixing the two, they
shouldn't be forced to pay for it, either the synchronization overhead
or the explicit function call to turn it off; only those using the
feature should be required to do something explicitly. What do you think?

In addition, doesn't the iostream library also incur the overhead of
a virtual function call for every character read or written?

--
Seungbeom Kim

f.fra...@gmx.net

unread,
Jul 31, 2008, 7:58:21 AM7/31/08
to
On 31 Jul., 06:28, Oncaphillis <oncaphil...@snafu.de> wrote:
> Oncaphillis wrote:
[snip]

> guess now i understand what you mean. the ability to have your
> values printed within different strings e.g. for internationalization.
> that's a big issue and if for example you look at the effort libraries
> like Qt take in QString::args I think there really isn't an easy solution.
> and (f|)printf doesn't help you much since different languages need
> different ordering for their args. That's the reason such libraries
> use placeholders like '%1'...'%5' in their format string instead
> of '%d' '%s'. And they come up with things like this:
>
> <snip>
> QString("Processing file %1 of %2: %3").arg(i).arg(total).arg(fileName);
> </snip>
>
> ...which isn't really beautiful AFAICS
>

Or you can use boost::format, which works with streams and
std::strings, for example like this:

cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" %
40.23 % 50;

Of course you won't get Qt's very good i18n features.

On the count of speed though the reputation is well earned with many
implementations.
The TR on C++ performance (http://www.open-std.org/jtc1/sc22/wg21/docs/
TR18015.pdf) has a detailed description.
We once noticed a considerable performance difference between visual c+
+ 2005 iostreams and both qt's stream implementation or printf based
reading when reading large files.

HTH

Fabio

Diego Martins

unread,
Jul 31, 2008, 4:07:21 PM7/31/08
to
On Jul 30, 7:34 pm, Thomas Richter <t...@math.tu-berlin.de> wrote:

> Diego Martins wrote:
> > - is printf really faster than streams in most of cases? where can I
> > find more info about that?
>
> I doubt that this is a reasonable argument. printf() and streams should
> be I/O bound, I would guess that the execution time of the call itself
> is irrelevant compared to the time to do the I/O (e.g. make the letters
> appear on the console).
>
> So long,
> Thomas

hi! I am still reading and evaluating your responses (very quick for a
moderated group. thanks!)

but right now, I have to disagree about the I/O boundness argument
(what about sprintf versus stringstream, for example?).

Diego

red floyd

unread,
Jul 31, 2008, 6:33:04 PM7/31/08
to
Seungbeom Kim wrote:

> I suspect that a significant portion of C++ programs do not bother to
> call sync_with_stdio(false), while not mixing stdio and iostream at all.
> I wonder, doesn't this violate the zero-overhead rule? Someone can
> argue: if programs are not using the feature of mixing the two, they
> shouldn't be forced to pay for it, either the synchronization overhead
> or the explicit function call to turn it off; only those using the
> feature should be required to do something explicitly. What do you think?
>

I suspect that it defaults to true so that you don't have to worry if
legacy libraries write to stdout/cout or stderr/cerr.

--

Eugene Gershnik

unread,
Aug 2, 2008, 12:43:21 PM8/2/08
to
On Jul 31, 4:19 am, Seungbeom Kim <musip...@bawi.org> wrote:
>
> My major complaints about the iostream library are:
>
> 1. It's tedious and verbose to set the formatting flags:
[...]

>
> 2. Formatting flags are persistent,
[...]

Agreed but IMHO these are just a manifestation of a larger problem.
Formatting information is not a property of a stream and, in general,
a stream has no business doing any formatting at all. Consider a
foobar class that doesn't have any notion of 'precision' for its
formatted output. What is the line

cout << setprecision(4) << foobar();

supposed to mean? It is obviously incorrect usage but it compiles and
runs just fine. It shouldn't. Such usage should either be impossible
or produce an error at runtime.

An output stream should be something that knows only to output
sequences of characters. Producing these sequences from objects and
feeding them into a stream should be left to a separate formatting
library (that's also where locales should live). An ideal output would
go along the lines

cout << format("08x", an_int)
<< " "
<< format(".2", a_float)
<< format(foobar())
<< format("my_custom$3$", foobar());

This doesn't preclude simple cout << 1; usage but it has to be defined
in terms of some default format(...).

Such an approach can be emulated today but inefficiently and without
removing the cost of all the unnecessary iostream cruft.

> I know there are solutions such as Boost.Format, but I doubt if
> that's just an extra layer of abstraction, adding the cost of parsing
> the format string while not eliminating the cost of manipulating
> the formatting flags (and of course the virtual function call).

Exactly.

--
Eugene

Jerry Coffin

unread,
Aug 2, 2008, 6:00:29 PM8/2/08
to
In article <579e850e-f681-4863-b286-
13d312...@p10g2000prf.googlegroups.com>, gers...@gmail.com says...

[ ... ]

> An output stream should be something that knows only to output
> sequences of characters. Producing these sequences from objects and
> feeding them into a stream should be left to a separate formatting
> library (that's also where locales should live).

That's exactly how things work now, except that the names are different.
A stream buffer knows only about reading/writing streams of characters.
A stream is a formatting class that's attached to a stream buffer that
acts as its source or sink -- but all the stream itself does is
format/parse data going to/coming from the stream buffer.

Now, there does appear to be one basic difference: you'd (apparently)
like to create a formatting object on the fly, feed it all the
formatting flags, have it format an object, and then destroy that
object. By contrast, the iostreams classes are designed so the
formatting object is more more permanent, and with at least some
capability to store formatting information in the longer term.

Your alternative is certainly a viable possibility, but you should be
aware that 1) it's primarily a difference in degree rather than kind --
i.e. while it's _typical_ to create a stream and allow it to create a
stream buffer, it's entirely possible to create a stream buffer, then
attach stream objects to that stream buffer as you see fit, each (for
example) with a separate set of format flags, and 2) that your setup is
likely to require careful design to get good efficiency -- in
particular, since you're likely to create and destroy a lot of
formatting objects, you need to be sure doing so is fairly inexpensive.

An ideal output would
> go along the lines
>
> cout << format("08x", an_int)
> << " "
> << format(".2", a_float)
> << format(foobar())
> << format("my_custom$3$", foobar());
>
> This doesn't preclude simple cout << 1; usage but it has to be defined
> in terms of some default format(...).

The moment you do this, you have basically nothing more or less than a
mediocre imitation of the current iostreams architecture -- i.e. you've
taken the current architecture, but rather than its clean separation of
formatting from buffering, you advocate something that's supposed to be
a buffer, only it knows about _some_ default formatting...

> Such an approach can be emulated today but inefficiently and without
> removing the cost of all the unnecessary iostream cruft.

Quite the contrary: you've advocated virtually nothing that's not
already available via iostreams, but your idea:
1) has a poorly defined architecture, mixing some formatting
responsibility into the buffer class.
2) will require very careful design to avoid even worse efficiency from
the number of formatting objects you create and destroy.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Eugene Gershnik

unread,
Aug 3, 2008, 5:07:16 AM8/3/08
to
On Aug 2, 3:00 pm, Jerry Coffin <jcof...@taeus.com> wrote:
> In article <579e850e-f681-4863-b286-
> 13d312b60...@p10g2000prf.googlegroups.com>, gersh...@gmail.com says...

>
> [ ... ]
>
> > An output stream should be something that knows only to output
> > sequences of characters. Producing these sequences from objects and
> > feeding them into a stream should be left to a separate formatting
> > library (that's also where locales should live).
>
> That's exactly how things work now, except that the names are different.

Not really. You snipped the beginning of my post which argued that how
to format an object is a property of the object rather than some
general formatting class. Also see below.

> A stream buffer knows only about reading/writing streams of characters.

Except it also consults locale to do the conversion. Which is probably
the wrong place to do this kind of stuff.

> A stream is a formatting class that's attached to a stream buffer that
> acts as its source or sink -- but all the stream itself does is
> format/parse data going to/coming from the stream buffer.

I am aware of this. The problem is that this formatting class is
general rather than specific to the class being formatted. It also
intimately bound to the streambuf (usually it outright owns it).

> Now, there does appear to be one basic difference: you'd (apparently)
> like to create a formatting object on the fly, feed it all the
> formatting flags, have it format an object, and then destroy that
> object.

No this is not the real difference. I believe that the formatting is
ought to be bound to the object rather than the sink. Whether you
create the formatting objects on the fly or reuse them is up to you.

> Your alternative is certainly a viable possibility, but you should be
> aware that

[...]

> while it's _typical_ to create a stream and allow it to create a
> stream buffer, it's entirely possible to create a stream buffer, then
> attach stream objects to that stream buffer as you see fit, each (for
> example) with a separate set of format flags

Well try it and see if it works. First you have the overhead of
creating a general stream object with all its bases and information.
Then by default streams assume that they own the buffer. Streams are
simply not designed to be used this way. While you can probably make
it work it misses the whole point. The meaningless

some_stream << setprecision(4) << foobar();

is still valid.

[...]

> 2) that your setup is
> likely to require careful design to get good efficiency -- in
> particular, since you're likely to create and destroy a lot of
> formatting objects, you need to be sure doing so is fairly inexpensive.

It can be done inexpensively and I believe that results could be much
faster than the current iostreams.

> An ideal output would
>
> > go along the lines
>
> > cout << format("08x", an_int)
> > << " "
> > << format(".2", a_float)
> > << format(foobar())
> > << format("my_custom$3$", foobar());
>
> > This doesn't preclude simple cout << 1; usage but it has to be defined
> > in terms of some default format(...).
>
> The moment you do this, you have basically nothing more or less than a
> mediocre imitation of the current iostreams architecture -- i.e. you've
> taken the current architecture, but rather than its clean separation of
> formatting from buffering, you advocate something that's supposed to be
> a buffer, only it knows about _some_ default formatting...

I think you completely misunderstood what I meant by example above. A
stream should know how to output character sequences and some kind of
'sequence producer' only. It doesn't need to know anything about *any*
default formatting.

--
Eugene


--

Seungbeom Kim

unread,
Aug 3, 2008, 5:04:22 AM8/3/08
to
Jerry Coffin wrote:
>
> Now, there does appear to be one basic difference: you'd (apparently)
> like to create a formatting object on the fly, feed it all the
> formatting flags, have it format an object, and then destroy that
> object. By contrast, the iostreams classes are designed so the
> formatting object is more more permanent, and with at least some
> capability to store formatting information in the longer term.

If the iostreams classes are intended to be the way they are now,
that's... too bad.

When you use "%d" or "%g" (without any further specification) in stdio,
you know exactly how the output will be formatted: as a decimal integer
and a general floating-point with the default precision, without any
padding.

In contrast, if you insert an_int or a_double into a basic_ostream
without any format specification, you never know how the numbers will
be formatted: an_int may be in decimal or hexadecimal or whatever,
a_double may be general, fixed, or scientific, with an unknown precision,
both with an unknown amount of padding, because you never know what
the previously called functions might have set for the stream (except
when you do know :D).

This makes the "current" formatting properties stored in the iostream
object pretty useless. To be sure of the formatting used, you should
either: (1) set every relevant formatting flag explicitly, at least
after calling a stream I/O function, or (2) conform to the requirement
that every stream I/O function should save the flags at the beginning
and restore them at the end. See James Kanze's formatting classes *Fmt
and StateSavingManip at <http://kanze.james.neuf.fr/doc/en/IO/html/>,
for an example of approach (2).

> Quite the contrary: you've advocated virtually nothing that's not
> already available via iostreams, but your idea:
> 1) has a poorly defined architecture, mixing some formatting
> responsibility into the buffer class.
> 2) will require very careful design to avoid even worse efficiency from
> the number of formatting objects you create and destroy.

Then do you think the current design of iostreams is okay, despite
the problems I mentioned above? Or do you have any other approach to
solve the problems in mind?

--
Seungbeom Kim

Jerry Coffin

unread,
Aug 3, 2008, 4:17:27 PM8/3/08
to
In article <g72ou5$cb3$1...@news.stanford.edu>, musi...@bawi.org says...

[ ... ]

> In contrast, if you insert an_int or a_double into a basic_ostream
> without any format specification, you never know how the numbers will
> be formatted: an_int may be in decimal or hexadecimal or whatever,
> a_double may be general, fixed, or scientific, with an unknown precision,
> both with an unknown amount of padding, because you never know what
> the previously called functions might have set for the stream (except
> when you do know :D).

You make it sound like some random agent might be changed randomly by
some unknown agent. That's misleading at best -- it's only changed when
some part of your program changes it.

It is true that some parts are modal, and it's not at all obvious right
off what's modal and what's not, or why some particular things are modal
or others aren't.

> This makes the "current" formatting properties stored in the iostream
> object pretty useless.

Nonsense. The code in your program is the only thing that can change
them. If you have so little idea of what's happening in your program
that something might produce output without knowing what formatting is
currently in effect, then you have a _serious_ problem in your program,
that has nothing whatsoever to do with the design of iostreams.

Don't get me wrong: overall, I tend to view modality as a shortcoming,
and I prefer to avoid it in general. Nonetheless, its real effects in
the case of iostreams are pretty minimal at worst.

[ ... ]

> > Quite the contrary: you've advocated virtually nothing that's not
> > already available via iostreams, but your idea:
> > 1) has a poorly defined architecture, mixing some formatting
> > responsibility into the buffer class.
> > 2) will require very careful design to avoid even worse efficiency from
> > the number of formatting objects you create and destroy.
>
> Then do you think the current design of iostreams is okay, despite
> the problems I mentioned above? Or do you have any other approach to
> solve the problems in mind?

I think the current design could be improved, but what's he's advocated
looks to me like it'd do more harm than good.

--
Later,
Jerry.

The universe is a figment of its own imagination.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Andre Kaufmann

unread,
Aug 3, 2008, 11:20:43 PM8/3/08
to
Diego Martins wrote:
> [...]

> - is printf really faster than streams in most of cases? where can I
> find more info about that?

Some ostream implementations use printf (sprintf) internally, perhaps
for consistency reasons - but I'm not sure about that.
So for these implementations ostreams can't be faster than printf.
My impression is that many implementations of iostreams, stringstreams,
fstreams etc. are pretty slow, compared to their C counterparts.

> - b) is a very strong issue! for example, format strings allows

> [...]
Another issue for me is readability. Using ostreams the formatting gets
pretty unreadable.

> Diego
> HP

Andre

Maciej Sobczak

unread,
Aug 4, 2008, 7:08:18 AM8/4/08
to
On 30 Lip, 20:58, Diego Martins <jose.di...@gmail.com> wrote:

> Sometimes, I find code where the developers prefer to use printf/
> fprintf, instead of ostream classes. They claim:
> a) performance reasons

If performance is an issue, IOStreams tend to perform rather badly.
This is due not only to the internal handling and potential dependency
on stdio (in which case it cannot be faster than stdio), but also to
the overhead of the heavily object-oriented design of the whole
library. It does not mean that OO alone makes it slow, but certainly
there are places where virtual function calls prevent compilers from
doing some optimizations that would be otherwise quite easy.

Please have a look at a simple replacement library that has been
designed specifically to allow aggressive compiler optimizations.
Performance charts are included further down the page:

http://www.msobczak.com/prog/fastreams/

> b) the ability of quickly replacing the format string

The above library supports that as well.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Seungbeom Kim

unread,
Aug 11, 2008, 4:58:59 AM8/11/08
to
Jerry Coffin wrote:
> In article <g72ou5$cb3$1...@news.stanford.edu>, musi...@bawi.org says...
>
>> In contrast, if you insert an_int or a_double into a basic_ostream
>> without any format specification, you never know how the numbers will
>> be formatted: an_int may be in decimal or hexadecimal or whatever,
>> a_double may be general, fixed, or scientific, with an unknown precision,
>> both with an unknown amount of padding, because you never know what
>> the previously called functions might have set for the stream (except
>> when you do know :D).
>
> You make it sound like some random agent might be changed randomly by
> some unknown agent. That's misleading at best -- it's only changed when
> some part of your program changes it.
>
> It is true that some parts are modal, and it's not at all obvious right
> off what's modal and what's not, or why some particular things are modal
> or others aren't.

Even if it's some part of my program, there can be a lot of them since
most I/O routines are included, and the fact stays the same that I don't
want to be distracted by side effects they cause.

>
>> This makes the "current" formatting properties stored in the iostream
>> object pretty useless.
>
> Nonsense. The code in your program is the only thing that can change
> them. If you have so little idea of what's happening in your program
> that something might produce output without knowing what formatting is
> currently in effect, then you have a _serious_ problem in your program,
> that has nothing whatsoever to do with the design of iostreams.

I don't mean I have no idea of what's happening, but do you really want
to keep track of the details of formatting flag changes that happen as
you call subroutines? Which one do you think is better:

std::ostream& operator<<(std::ostream& os, const VirtualTime& t);

Effects: prints the virtual time t into os (in such and such format).

versus

std::ostream& operator<<(std::ostream& os, const VirtualTime& t);

Effects: sets std::ios_base::fixed, width 8, precision 4 on os,
and prints the virtual time t into os.

or

std::ostream& operator<<(std::ostream& os, const VirtualTime& t);

Effects: prints the virtual time t into os (in such and such format).
Side effects: sets std::ios_base::fixed, width 8, precision 4 on os.

? Do you really want to keep in mind that the state of os is changed
after you print a VirtualTime object into os?

>
> Don't get me wrong: overall, I tend to view modality as a shortcoming,
> and I prefer to avoid it in general. Nonetheless, its real effects in
> the case of iostreams are pretty minimal at worst.

If you care about the formats, you have to do something: either have
the subroutines revert to the old state every time after changing it,
or don't depend on the current state and set every flag you care about
before any I/O. That may not the greatest frustration, but a great
annoyance that you encounter often, here and there.

If a state saving class is the answer, I'd like to see one standardized
at least so that I don't have to export and explain mine from my tool
box or try to understand others' every time.

--
Seungbeom Kim

0 new messages