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

vinoth.ree has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I was getting the benefit of buffering in case of reading from the disk, But when I write log message to a file, I have not getting the message immediately, If I write to STDOUT its printing immediately because it is attached with terminal so it is lined buffer. To get log message immediately I use the select filenadle and set the $| to true. It will flush the buffer immediately, Instead of flushing the buffer can't we disable the buffering itself ?

Vinoth,G

Replies are listed 'Best First'.
Re: How to turn off buffering ?
by lakshmananindia (Chaplain) on Jun 03, 2009 at 06:25 UTC

    Buffering is used by Perl for efficiency reasons.

    System calls are always expensive, and to reduce that we need buffering.

    It is always good to flush the buffering, instead of removing the buffering itself.

    In Perl, you can't turn the buffering off and it is stated in Suffering from Buffering

    --Lakshmanan G.

    The great pleasure in my life is doing what people say you cannot do.


      Is it so..
Re: How to disable buffering ?
by sgifford (Prior) on Jun 03, 2009 at 06:44 UTC
    Sure, setting $| to true disables buffering for the current filehandle until it is set back to false. You don't have to re-set it for every line of output.
Re: How to disable buffering ?
by targetsmart (Curate) on Jun 03, 2009 at 06:42 UTC
    well said by lakshmananindia ++

    Why do you do select everytime on filehandles and then set $| to true, that is not a good idea
    you can use IO::Handle or FileHandle modules to open the files and set autoflush on that handle to true, that will avoid using select everytime on different handles and setting $|=1

    Instead of flushing the buffer can't we disable the buffering itself ?
    buffering is our friend, saves a lot of time for us, so don't think our disabling buffering


    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
Re: How to disable buffering ?
by ig (Vicar) on Jun 04, 2009 at 03:14 UTC
    Instead of flushing the buffer can't we disable the buffering itself ?

    I don't think there is much difference between flushing the buffer with every print or write and disabling the buffering, at least from an external perspective (i.e. without looking at the code that implements the functions). But you may mean something different than what I understand.

    You may find PerlIO interesting. You can open a file with the 'unix' layer specified, in which case it is unbuffered, at least on my linux system.

    use strict; use warnings; open(my $fh, '>:unix', "test.txt") or die "test.txt: $!"; foreach my $i (1..20) { print $fh "iteration $i\n"; sleep(5); } close($fh);

    Perhaps this satisfies your definition of "disable the buffering".

    You might also be interested to investigate the setbuf and setvbuf methods of IO::Handle.

    Another option is to use syswrite which "bypasses buffered IO".

    update: If you are interested in manipulating the I/O stack on a filehandle that is already open, such as STDOUT, you can use binmode (at least you can on linux, I don't know if this would work on all or any other platforms):

    use strict; use warnings; use PerlIO; print join(', ', PerlIO::get_layers(*STDOUT)) . "\n"; binmode(*STDOUT, ":pop"); print join(', ', PerlIO::get_layers(*STDOUT)) . "\n"; __END__ unix, perlio unix

    After this change, output to STDOUT is unbuffered even if STDOUT is redirected to a file or pipe.

      You might also be interested to investigate the setbuf and setvbuf methods of IO::Handle.

      Problem with those is that they're usually not available starting with Perl 5.8.0, because they rely on stdio, while newer perls are typically built with perlio...

      $ perl -MIO::Handle -e'IO::Handle->new->setvbuf($buf,1,1024)' IO::Handle::setvbuf not implemented on this architecture at -e line 1.

      (But it's still recommended to read the respective C man page for setvbuf - even if you can't use that functionality from Perl :)  - as it gives a nice introduction to buffering in general, i.e. block-buffered vs. line-buffered vs. unbuffered, etc.)