[net.unix] why is fprintf

wsmith@uiucdcsb.CS.UIUC.EDU (08/18/86)

I was doing some performance testing on a program and as part of it
I was doing about 500 fprintf(stderr, "blah...\n");

The program was taking 35 or 40 seconds of system time which was pretty
high.  I then commented out the fprintf's and the program took 17 or 18
system time seconds (it was doing a lot of disk accesses).

Is this well known behavior that fprintf(stderr, ... ) takes a lot of time?
Why does it do so?

Bill Smith
ihnp4!uiucdcs!wsmith
wsmith@b.cs.uiuc.edu

jrw@hropus.UUCP (Jim Webb) (08/18/86)

> I was doing about 500 fprintf(stderr, "blah...\n");
> 
> The program was taking 35 or 40 seconds of system time which was pretty
> high.  I then commented out the fprintf's and the program took 17 or 18
> system time seconds (it was doing a lot of disk accesses).

Standard error is unbuffered, eg, one char at a time, so it makes one
write system call per character, hence its slowness.
-- 
Jim Webb             "Out of phase--get help"         ihnp4!houxm!hropus!jrw

brent@poseidon.UUCP (Brent P. Callaghan) (08/19/86)

> Standard error is unbuffered, eg, one char at a time, so it makes one
> write system call per character, hence its slowness.
                    ^^^^^^^^^^^^^

Surely you mean "per call".

-- 
				
Made in New Zealand -->		Brent Callaghan
				AT&T Information Systems, Lincroft, NJ
				{ihnp4|mtuxo|pegasus}!poseidon!brent
				(201) 576-3475

jrw@hropus.UUCP (Jim Webb) (08/19/86)

> > Standard error is unbuffered, eg, one char at a time, so it makes one
> > write system call per character, hence its slowness.
>                     ^^^^^^^^^^^^^
> 
> Surely you mean "per call".

Nope, "per character" makes much more sense than "it makes one write system
call per call."
-- 
Jim Webb             "Out of phase--get help"         ihnp4!houxm!hropus!jrw

chris@umcp-cs.UUCP (Chris Torek) (08/20/86)

In article <19300053@uiucdcsb> wsmith@uiucdcsb.CS.UIUC.EDU writes:
>I was doing some performance testing on a program and as part of it
>I was doing about 500 fprintf(stderr, "blah...\n");

>The program was taking 35 or 40 seconds of system time which was pretty
>high.  I then commented out the fprintf's and the program took 17 or 18
>system time seconds (it was doing a lot of disk accesses).

stderr is `traditionally' unbuffered.  That means that fprintf()s
to it write one character at a time.  This is indeed quite expensive.
The 4.3BSD fprintf---or more precisely, _doprnt---temporarily turns
on block buffering for some (but not all) operations.  I have, in
the past, added a `setbuf' or `setlinebuf' call to force buffering
on stderr.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

henry@utzoo.UUCP (Henry Spencer) (08/26/86)

> > Standard error is unbuffered, eg, one char at a time, so it makes one
> > write system call per character, hence its slowness.
>                     ^^^^^^^^^^^^^
> 
> Surely you mean "per call".

It *ought* to be "per call".  On many systems, in *fact* it is "per character".
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry

eric@chronon.UUCP (Eric Black) (08/29/86)

In article <7074@utzoo.UUCP> henry@utzoo.UUCP (Henry Spencer) writes:
>> > Standard error is unbuffered, eg, one char at a time, so it makes one
>> > write system call per character, hence its slowness.
>> Surely you mean "per call".
>It *ought* to be "per call".  On many systems, in *fact* it is "per character".

Of course, the reason that it was made per character is to make sure that
the error output in fact gets out, and is not lost in stdio buffering somewhere
when an errant program suddenly gives up the ghost.  On BSD systems,
at least, you can change this with the setlinebuf(3S) call, to make
stderr use buffering.  Nowadays, with buffered stdio output less likely
to get lost (?), perhaps it is too bad that the default is still
to make a system call per character, rather than per call, but...

On non-BSD systems you're stuck, as far as I know.

-- 
Eric Black   "Garbage In, Gospel Out"
UUCP:        {sun,pyramid,hplabs,amdcad}!chronon!eric

chris@umcp-cs.UUCP (Chris Torek) (08/30/86)

In article <338@chronon.chronon.UUCP> eric@chronon.UUCP (Eric Black) writes:
>Of course, the reason that [stderr printfs use one system call]
>per character is to make sure that the error output in fact gets
>out....  On BSD systems, at least, you can change this with the
>setlinebuf(3S) call, to make stderr use buffering. ... On non-BSD
>systems you're stuck, as far as I know.

Not stuck: there is still setbuf(3S).  A fair fraction of my programs
begin with

	char	serrbuf[BUFSIZ];	/* buffer for stderr */

	main(...)
	{

		setbuf(stderr, serrbuf);

Further calls to fprintf(stderr) are immediately followed either
by exit(code), which flushes all stdio buffers, or an explicit
fflush(stderr).  It is possible to lose error output in some cases;
these I simply put up with, for a simple stack trace tends to
pinpoint them immediately anyway, and even adb prints readable
stack traces (so long as you have symbols!).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

meissner@dg_rtp.UUCP (Michael Meissner) (09/01/86)

In article <338@chronon.chronon.UUCP> eric@chronon.UUCP (Eric Black) writes:
>
>Of course, the reason that it was made per character is to make sure that
>the error output in fact gets out, and is not lost in stdio buffering somewhere
>when an errant program suddenly gives up the ghost.  On BSD systems,
>at least, you can change this with the setlinebuf(3S) call, to make
>stderr use buffering.  Nowadays, with buffered stdio output less likely
>to get lost (?), perhaps it is too bad that the default is still
>to make a system call per character, rather than per call, but...
>
>On non-BSD systems you're stuck, as far as I know.

On System V.2, V.3, and the ANSI X3J11 draft you can use setvbuf (which allows
to set both the buffersize and a choice between no/line/full buffering).  Also,
I believe a pure System V.2 system buffers per call to *printf instead of per
character (but I'm not sure).

	Michael Meissner, Data General
	...{ decvax, ucbvax }!mcnc!rti-sel!dg_rtp!meissner