http://www.perlmonks.org?node_id=978283

Diamondust has asked for the wisdom of the Perl Monks concerning the following question:

I was trying to write a simple while loop:

perl -e 'while(1){sleep 1; print 123;}' # prints nothing

perl -e 'while(1){sleep 1; print 123 . "\n";}' # this works

perl -e 'while(1){sleep 1; print "123\n";}' # this works also

perl -e 'for($i=0; $i < 10; $i++){sleep 1; print $i;}' # this works but prints nothing within 10 seconds.

I seems that perl does not flush a printed string without seeing a NL character, is that the right interpretation of this peculiar behavior?
Can this be considered as a bug then?

Replies are listed 'Best First'.
Re: The delay of printing encountered using loop
by Perlbotics (Archbishop) on Jun 25, 2012 at 21:54 UTC

    I seems that perl does not flush a printed string without seeing a NL character, is that the right interpretation of this peculiar behavior?
    Correct. It's the expected behaviour of STDOUT to operate in buffered mode. NL marks the end of the line and then the whole line is printed.
    Can this be considered as a bug then?
    Maybe not, with the weak excuse that it has been always working like that.

    Buffering has some performance advantages when giving bigger chunks of characters to the OS rather than calling some I/O function of the OS for each individual character.

    You can switch off buffering, setting $| to true.

    perl -e '$|=1; for($i=0; $i < 10; $i++){sleep 1; print $i;}'

    STDERR is unbuffered by default, so this works too (but uses a different stream):

    perl -e 'for($i=0; $i < 10; $i++){sleep 1; print STDERR $i;}'

    Here's the obligatory article: Suffering from Buffering

      That's very interesting.
      I guess my initial experience on Turbo C gave me this opposite feeling.
      #include <stdio.h> /* #include <unistd.h> */ main(){ while(1){ sleep(1); printf("123"); } return 0; }

      The above code, when running on Windows Turbo C, it prints 123 every second without the necessity of a NL character. But when compiled on g++ on Unix, it never prints anything because of no NL for the stream to be flushed.

      But ActicePerl on Windows has the same behavior as on Unix, i.e. it prints nothing without seeing an NL character.

      Is this because Perl tries hard to make itself platform independent, or it's because that Turbo C is archaic and has such different behavior than every one else?

        I would guess it's Turbo C being not so turbo...

        (It's not g++'s fault. It's the C library's fault. Back in DOS-land, compilers actually came with their own C libraries.[citation needed] Perl emulates its own print commands, and with it, has its own output buffers.)

Re: The delay of printing encountered using loop
by frozenwithjoy (Priest) on Jun 25, 2012 at 22:02 UTC
    Probably overkill for a one-liner, but for something longer you can control flushing with the flush/autoflush-related functions/methods from IO::Handle. edit: one nice thing about this approach is that you can specify how different file handles get flushed. For example, auto-flushing log files only gives you up-to-date logs, but doesn't cause the performance penalty of auto-flushing file handles used for big data.
      one nice thing about this approach is that you can specify how different file handles get flushed.
      I agree that using IO::Handle methods is nicer but just the approach with $| allows for the same granularity.

      It is not the case that setting $| to true turns on autoflushing for all file-handles. It only affects the file-handle that had been selected (or STDOUT when none had been explicitely selected).

      see "perldoc -f select"