[comp.unix.questions] Question on printf

jian@kuhub.cc.ukans.edu (06/07/90)

Hi folks, I have one simple question about printf() on Utrix. Following is the
program that I question about:

#define <stdio.h>
#define <signal.h>

main()
{ 
  ....
  
  alarm(60);

  ....
  
  signal(SIGALRM, display);

  ....

} /* main() */

display()
{ 
   printf("\n\n\nEnter Command -> ");
   alarm(60);
}

I don't know why the printf() only prints three linefeeds and the "Enter 
Command -> " only shows up on every next call to display. It seems to me
that if I don't do any I/O and linefeed after printf(), the printf() does 
not print the string argument on the standard output. Why? How can I avoid
this problem? I very much appreciate any helps.

Jian Li 
jian@kuhub.cc.ukans.edu

gwyn@smoke.BRL.MIL (Doug Gwyn) (06/08/90)

In article <24674.266e3b81@kuhub.cc.ukans.edu> jian@kuhub.cc.ukans.edu writes:
>that if I don't do any I/O and linefeed after printf(), the printf() does 
>not print the string argument on the standard output. Why? How can I avoid
>this problem?

Just insert the following immediately after you call printf():
	fflush(stdout);
This will force the data buffered by stdio for the stdout stream
to be sent to the output device; normally that occurs only at
each new-line.

cpcahil@virtech.uucp (Conor P. Cahill) (06/08/90)

In article <24674.266e3b81@kuhub.cc.ukans.edu> jian@kuhub.cc.ukans.edu writes:
>display()
>{ 
>   printf("\n\n\nEnter Command -> ");
>   alarm(60);
>}
>
>I don't know why the printf() only prints three linefeeds and the "Enter 
>Command -> " only shows up on every next call to display. It seems to me

The problem is caused by the fact that you are writing the data throught
the standard i/o buffer which for a tty is line buffered.  This means that
your data will not appear until a newline is output.

To fix this you could do any of the following:

1. use write(2) instead of printf.  writes are not buffered and the data
will be sent directly out to the screen.

2. add the line fflush(stdout) following the printf (although I would also
recommend that you then use fprintf(stdout,...) instead of printf() just so
that it is very plain what you are flushing).

3. add a setbuf(stdout,(char *) 0) at the begining of your program.  This 
turns off all output buffering and can have a detrimental effect on the
overall performance of your software.  

For what you are doing, #2 is probably the best solution.


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

jeff@quark.WV.TEK.COM (Jeff Beadles;685-2568;;;quark) (06/08/90)

In article <24674.266e3b81@kuhub.cc.ukans.edu> jian@kuhub.cc.ukans.edu writes:
|Hi folks, I have one simple question about printf() on Utrix. Following is the
|program that I question about:

...

|display()
|{ 
|   printf("\n\n\nEnter Command -> ");

Insert the line:
	fflush(stdout);

|   alarm(60);
|}
|
|I don't know why the printf() only prints three linefeeds and the "Enter 
|Command -> " only shows up on every next call to display. It seems to me
|that if I don't do any I/O and linefeed after printf(), the printf() does 
|not print the string argument on the standard output. Why? How can I avoid
|this problem? I very much appreciate any helps.
|
|Jian Li 
|jian@kuhub.cc.ukans.edu


Things will work much better with the fflush.  The problem is that stdio is
buffered by default, and is waiting for a \n to flush the output buffer.


	-Jeff

-- 
Jeff Beadles				jeff@quark.WV.TEK.COM 
Utek Engineering, Tektronix Inc.	+1 503 685 2568
			SPEEA - Just say no.

jpr@dasys1.uucp (Jean-Pierre Radley) (06/15/90)

In article <1990Jun8.030206.4532@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
> [as one of the ways to geta printf() call to show up right away]

>3. add a setbuf(stdout,(char *) 0) at the begining of your program.  This 
>turns off all output buffering and can have a detrimental effect on the
>overall performance of your software.  

Why is that?
-- 
Jean-Pierre Radley						   jpr@jpradley
New York, NY					      72160.1341@compuserve.com

cpcahil@virtech.uucp (Conor P. Cahill) (06/15/90)

In article <1990Jun15.042610.18292@dasys1.uucp> jpr@dasys1.UUCP (Jean-Pierre Radley) writes:
>In article <1990Jun8.030206.4532@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>> [as one of the ways to geta printf() call to show up right away]
>
>>3. add a setbuf(stdout,(char *) 0) at the begining of your program.  This 
>>turns off all output buffering and can have a detrimental effect on the
>>overall performance of your software.  
>
>Why is that?

Because it causes all output be be written immediatly.  If you are using
something like curses for a full screen program it noticably slows down 
the screen drawing. (Enough that an end-user will notice and complain about
it).

Normally output is not written to stdout (that is associated with a tty) until
a newline is sent.  When stdout is redirected to a file, it is buffered for 
a full stdio block.  Using setbuf() turns off all buffering.



-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

gwyn@smoke.BRL.MIL (Doug Gwyn) (06/16/90)

In article <1990Jun15.042610.18292@dasys1.uucp> jpr@dasys1.UUCP (Jean-Pierre Radley) writes:
>>3. add a setbuf(stdout,(char *) 0) at the begining of your program.  This 
>>turns off all output buffering and can have a detrimental effect on the
>>overall performance of your software.  
>Why is that?

Because it turns off buffering on the stdout stream!
I suppose your real question is, what is buffering good for.
By buffering several sequential putchar()s (or equivalent)
in a data area belonging to the C library stdio implementation
(linked into your application), and performing a system call
to write out the entire buffer just once when the buffer fills
up (or, in some circumstances, whenever a new-line character
is seen), instead of a system call per character as must be
done when buffering is disabled, obviously the number of
system calls to transfer the same amount of data is
drastically reduced. Since there is considerable overhead
involved in making a system call, minimimizing the number of
system calls made leads to better application performance.

hunt@dg-rtp.dg.com (Greg Hunt) (06/17/90)

In article <13132@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
|> In article <1990Jun15.042610.18292@dasys1.uucp> jpr@dasys1.UUCP
(Jean-Pierre Radley) writes:
|> >>3. add a setbuf(stdout,(char *) 0) at the begining of your program.  This 
|> >>turns off all output buffering and can have a detrimental effect on the
|> >>overall performance of your software.  
|> >Why is that?
|> 
|> Because it turns off buffering on the stdout stream!
|> I suppose your real question is, what is buffering good for.
|> By buffering several sequential putchar()s (or equivalent)
|> in a data area belonging to the C library stdio implementation
|> (linked into your application), and performing a system call
|> to write out the entire buffer just once when the buffer fills
|> up (or, in some circumstances, whenever a new-line character
|> is seen), instead of a system call per character as must be
|> done when buffering is disabled, obviously the number of
|> system calls to transfer the same amount of data is
|> drastically reduced. Since there is considerable overhead
|> involved in making a system call, minimimizing the number of
|> system calls made leads to better application performance.
|> 

While the cost of doing the extra system calls is something to be
considered, I believe that the more significant cost associated with
doing multiple I/O's is the actual time it takes the device to do the
I/O.  Devices are very slow compared to operations purely done in
memory (like buffering).

Most devices that I know of, including disks, tapes, and terminals,
all have different throughput rates depending on the size of the I/O
being done.  Some disks that I have worked with, for example, can
handle a single block I/O request in about .020 seconds.  If you try
a two block I/O, you'll find it is also handled in about the same
amount of time.  This continues until you hit some design point where
you'll see a sharp increase in the time it takes, say between 20 and
21 block I/O's.  Then the pattern continues for another 20 blocks.

So, if you need to write 20 blocks, you could write them one block
at a time, but this would take 20 * .020 seconds, or .400 seconds.  On
the other hand, you could write all 20 blocks at once, which would only
take you about .020 seconds.  That difference is why buffering, where
applicable, makes a great deal of sense.  It can be a huge performance
win.  The cost of the system calls itself is a contributing factor, but
the speed of the device is a greater factor, I think.

I believe that terminals exhibit this same pattern, but of course the
I/O times are probably quite different from the speed of a disk drive.

The pattern is highly dependent on the device's and controller's
characteristics, and the way the operating system interacts with the
device.  The pattern is not necessarily linear or even regular.  There
are frequently bizzare spikes that cannot easily be explained.

Of course, your mileage may vary.

--
Greg Hunt                        Internet: hunt@dg-rtp.dg.com
Data Management Development      UUCP:     {world}!mcnc!rti!dg-rtp!hunt
Data General Corporation
Research Triangle Park, NC       These opinions are mine, not DG's.