什么是魔术标点“$ |”的替代品在Perl中关闭打印缓冲区?

时间:2011-07-04 06:01:59

标签: perl cgi

我正在重构一些旧代码(由其他人重构),我在一些CGI脚本的顶部遇到了以下内容:

#Turn on output buffering
local $| = 1;
像往常一样,perlcritic没有帮助指出显而易见的:“使用魔术标点符号”。是否有任何替代方案或perlcritic只是脾气暴躁?

此外,仔细检查。我认为代码是错误的。

如果我没有弄错的话,这意味着与评论所说的完全相反。它将关闭输出缓冲。我的记忆有点生疏,我似乎无法找到描述这个神奇标点符号的Perl文档。脚本在mod_perl中运行。

是否需要弄乱Perl的缓冲行为并获得任何性能提升?关于此的大部分内容都来自21世纪头十年的早期。这仍然是一种有效的良好做法吗?

4 个答案:

答案 0 :(得分:9)

$|是许多标点符号变量中的一个,它们实际上是每个文件句柄。该变量获取或设置当前所选输出文件句柄的值(默认情况下为STDOUT)。 ($.略有不同;它绑定到从中读取的最后一个文件句柄。)

访问这些的“现代”方式是通过文件句柄上的方法:

use IO::Handle;
$fh->autoflush(1);  # instead of $|=1

perldoc perlvar中记录了与每个变量对应的方法。

答案 1 :(得分:6)

你的问题似乎有点分散,但我会尽力回答。

您想阅读perldoc pervarrelevant section说:

   $|      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.)

是的,评论不正确。设置$| = 1确实禁用缓冲,而不是打开它。

至于性能,默认情况下启用输出缓冲的原因是因为这可以提高性能 - 即使在2011年 - 并且可能直到时间结束,除非量子I / O以某种方式改变我们完全理解I / O的方式

禁用输出缓冲的原因不是为了提高性能,而是以牺牲性能为代价来改变其他行为

由于我不知道你的代码是做什么的,所以我不能推测它想要禁用输出缓冲的原因。

禁用输出缓冲的一些(但绝不是全部)可能的原因:

  • 您正在写入套接字或管道,而另一端则需要立即响应。
  • 您正在向控制台写入状态更新,并希望用户立即查看它们,而不是在行尾。当您在许多操作之后输出句点等时,这种情况尤为常见
  • 对于CGI脚本,您可能希望浏览器在处理完成之前显示一些HTML输出。

答案 2 :(得分:4)

正如其他人所说,评论是不正确的。相反,local $| = 1禁用输出缓冲。

要遵守Perl::Critic的政策,您可以使用English模块:

use English qw( -no_match_vars );

local $OUTPUT_AUTOFLUSH = 1;  # equivalent to: local $| = 1

答案 3 :(得分:1)

正如你可以检查手册,$ | = 1关闭缓冲,说必须刷新缓冲区,所以注释是错误的。

关于它的好坏,我不知道,但我也看到过总是在CGI脚本中完成,所以我怀疑在这种特殊情况下这是好事,也许是因为通常CGI脚本想要在编写数据后立即提供数据。