IO.putc and $stdout.sync

It’s often useful to provide some sort of output when a script is waiting for something or running a loop that take a while to complete.  Instead of writing a bunch of output and running the risk of scrolling useful information off the page, I like writing out a single ‘.’ every once in a while, just to let me know the script hasn’t hung.

The problem with just writing a ’.' is that most terminals/operating systems use a feature called “buffering”.  When you write to a file (or terminal/stdout) the operating system doesn’t immediately flush that output to where you are writing.  It will wait until a sufficient amount of data has been written, and then flush it all out at the same time to save on resources/system calls.  A single ‘.’ is nowhere near enough data to signal the OS to flush that output, so you’ll end up seeing a bunch of them all written when the loop completes, or worst yet, nothing until the script is finished.  For example:

#!/usr/bin/env ruby
20.times do
putc('.')
sleep(5)
end

On first glance, you’d think this script would print 20 dots on a line, one every 5 seconds, but it doesn’t! When run, it sits there for a full minute without outputting anything, and then spits out 20 dots right before quitting. We need to turn off write buffering on $stdout by turning on sync mode:
$stdout.sync=(true) if not $stdout.sync

If you add that line to the top of the script, each dot is written to the terminal right away.

This entry was posted on Friday, April 27th, 2007 at 10:35 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Be the first to leave a comment.

Leave a Reply