Reputation: 7605
I was refactoring some old code (by other people) and I came across the following at the top of some CGI scripts:
#Turn on output buffering
local $| = 1;
perlcritic as usual unhelpfully points out the obvious : "Magic punctuation used". Are there any alternatives to this or perlcritic is just grumpy?
Furthermore, on closer inspection. I think the code is wrong.
If I'm not mistaken, it means exactly the opposite from what the comment says. It turns off the output buffering. My memory is a little bit rusty and I can't seem to find the Perl documentation that describes this magic punctuation. The scripts run in mod_perl.
Does messing around with Perl's buffering behavior desirable and results in any performance gain? Most of the stuff written about this comes from the early part of the first decade of the 21st century. Is this still even a valid good practice?
Upvotes: 3
Views: 1073
Reputation: 79784
Your question seems a bit scattered, but I'll try my best to answer thoroughly.
You want to read perldoc pervar
. The relevant section says:
$| If set to nonzero, forces a flush right away and after every write or print on the currently selected output channel. Default is 0
(regardless of whether the channel is really buffered by the system or not; $| tells you only whether you've asked Perl explicitly to
flush after each write). STDOUT will typically be line buffered if output is to the terminal and block buffered otherwise. Setting this
variable is useful primarily when you are outputting to a pipe or socket, such as when you are running a Perl program under rsh and want
to see the output as it's happening. This has no effect on input buffering. See "getc" in perlfunc for that. See "select" in perldoc
on how to select the output channel. See also IO::Handle. (Mnemonic: when you want your pipes to be piping hot.)
So yes, the comment is incorrect. Setting $| = 1
does indeed disable buffering, not turn it on.
As for performance, the reason output buffering is enabled by default is because this improves performance--even in 2011--and probably until the end of time, unless quantum I/O somehow changes the way we understand I/O entirely.
The reasons to disable output buffering are not to improve performance, but to change some other behavior at the expense of performance.
Since I have no idea what your code does, I cannot speculate as to its reason for wanting to disable output buffering.
Some (but by no means all) possible reasons to disable output buffering:
Upvotes: 6
Reputation: 74292
The comment, as others have stated, is incorrect. In contrast, local $| = 1
disables output buffering.
To comply with Perl::Critic
's policies, you could make use of the English
module:
use English qw( -no_match_vars );
local $OUTPUT_AUTOFLUSH = 1; # equivalent to: local $| = 1
Upvotes: 4
Reputation: 98508
$|
is one of a number of punctuation variables that are really per-filehandle. The variable gets or sets the value for the currently selected output filehandle (by default, STDOUT). ($.
is slightly different; it is bound to the last filehandle read from.)
The "modern" way to access these is via a method on the filehandle:
use IO::Handle;
$fh->autoflush(1); # instead of $|=1
The method corresponding to each variable is documented in perldoc perlvar.
Upvotes: 9
Reputation: 9691
As you can check in manuals, $|=1 turn off buffering saying that it is true that the buffers must be flushed, so the comment is wrong.
About it being good or not, I don't know, but me too have seen that always done in CGI scripts, so I suspect it is a good thing in this particular case, maybe it is since normally CGI scripts want to make the data available as soon as they are written.
Upvotes: 1