Main Content

Buffering output - why it is done and issues raised in Tcl, Perl, Python and PHP

Archive - Originally posted on "The Horse's Mouth" - 2007-04-06 08:16:41 - Graham Ellis

When you go to board a plane at Heathrow, do the ground staff admit the passengers one at a time, ensuring that each is seated before the next boards, and sealing and re-opening the main doors between each? What a stupid and inefficient system that would be!!

The same thing applies when you're programming - outputs that you THINK that you're printing directly to screen, to file, to pipe, or (via a socket) to a process on another machine may in fact be waiting in the lounge - buffered - to be output with greater efficiency in a single block.

Should you wish to read from a newly written resource, then, you might have to wait. In the majority of cases it would not be a problem. Language libraries are usually built with a number of checkpoints at which data is "flushed" even if buffers aren't full. Such flushes commonly occur:
a) When a new line is generated (keep screen up to date)
b) When an input is about to be read (so that prompts can be seen!)
c) When the buffer reaches 4k of data
d) When the file handle is closed
e) When the program exits
and these account for most, but not all, of the cases the programmer needs to be aware of.

"But not all" I wrote. Here are some common exceptions:

In Tcl, the fconfigure command gives you channel by channel control. By default, flushing happens line by line (and so NOT when you're about to do a read) and this means you'll want to flush stdout after outputting a prompt with puts -nonewline. Otherwise, the prompt is only issued on the screen AFTER you've answered the question. [example]

In Perl, output is similarly flushed at new line, and in addition it is flushed at read. Good - no need for Tcl's flush. However, if you're generating a progress bar - either a series of dots or a line that's being overwritten time and again, then you'll need to flush. Have a look at autoflush and have a look at the special variable $| (that's dollar-pipe). Neither of these flushes itself - rather they add an extra flush at the end of each print. See
[/example].

Python has a similar arrangement to Perl, so it's quite rare that you need to flush the screen output - but again you DO need to do so with a progress bar. [example].

I describe PHP as being a "batch" or "batchlet" language - at least in its intended web use. So it doesn't have the interactive buffering issues associated with keyboard-to-screen in most uses. Actually, you have rather the opposite problem sometimes. In PHP, if you try to call the header function, or anything else that could effect the headers (even session_start can do it) after you have generated some output, you'll get an error message like Warning: Cannot modify header information - headers already sent by .... There *is* an ob_start function to turn ON output buffering but, really, best programming practise is to generate your headers early!

There are PHP examples broken here and working here. They include links to source.