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.