【发布时间】:2011-09-13 16:13:31
【问题描述】:
我最近有幸在我的 Perl 脚本中设置了$| = 1;,以帮助它通过管道更快地与另一个应用程序通信。
我很好奇为什么这不是默认设置。换句话说,如果我的缓冲区被立即刷新,我会失去什么?
【问题讨论】:
-
更快?不,可能不会,因为它会更频繁地被唤醒。不过,它的延迟会更低。
-
我经常希望如此。我不相信这种好处值得它所带来的所有麻烦。
我最近有幸在我的 Perl 脚本中设置了$| = 1;,以帮助它通过管道更快地与另一个应用程序通信。
我很好奇为什么这不是默认设置。换句话说,如果我的缓冲区被立即刷新,我会失去什么?
【问题讨论】:
写入文件描述符是通过系统调用完成的,系统调用很慢。
缓冲一个流并仅在写入一定数量的数据后刷新它是一种节省一些系统调用的方法。
【讨论】:
对它进行基准测试,你就会明白。
缓冲取决于输出句柄的设备类型:ttys是行缓冲的;管道和套接字是管道缓冲的;磁盘是块缓冲的。
这只是基本的编程。这不是 Perl 的东西。
【讨论】:
I/O 缓冲区刷新的次数越少,您的代码通常就越快(因为它不必经常进行系统调用)。因此,通过启用自动刷新,您的代码会花费更多时间等待 I/O。
在纯网络 I/O 驱动的应用程序中,这显然更有意义。但是,在最常见的用例中,行缓冲 I/O(Perl 对 TTY 的默认设置)允许程序不那么频繁地刷新缓冲区并花更多时间做 CPU 工作。一般用户不会注意到终端或文件中的差异。
【讨论】:
User-Agent 这样的大型 HTTP 标头行只有大约 120 个字节。短行可能少于 20 个字节。对于典型的 MTU,20 多个 HTTP 标头行应该很容易放入一个数据包中。如果您对 HTTP 标头进行行缓冲,大多数网络堆栈将每行吐出一个数据包。导致 TCP/IP 开销增加 20 倍。 HTTP 是不应进行行缓冲的协议的完美示例,而 IRC 是同样应进行行缓冲的协议的完美示例。