为什么缓冲区默认不自动刷新?

3

我最近有幸在我的Perl脚本中设置了$| = 1;,以帮助它通过管道更快地与另一个应用程序通信。

我很好奇为什么这不是默认设置。换句话说,如果我的缓冲区立即被刷新,我会失去什么?


2
更快吗?可能不是,因为它会更频繁地被唤醒。但它的延迟会更低。 - ikegami
我经常有同样的想法。但我并不确定这样做所带来的好处是否值得所有麻烦。 - ikegami
3个回答

13

通过系统调用来写入文件描述符,而系统调用是慢的。

缓冲流并在写入一定量的数据后才刷新它是一种节省系统调用的方法。


6
还有数据包、磁盘写入,以及……几乎所有需要一次性处理多个字节数据才能更好工作的东西 :) - Brian Roach

8

对其进行基准测试,您就会理解。

缓冲取决于输出句柄的设备类型:ttys为行缓冲;管道和套接字为管道缓冲;磁盘为块缓冲。

这只是基本编程。这不是Perl的特性。


3
尽量减少I/O缓冲区的刷新次数通常能提高代码执行速度(因为不需要频繁进行系统调用)。启用自动刷新会使代码更多地花费在等待I/O上。对于纯网络I/O驱动的应用程序,这显然是更合理的。但是,在大多数常见的情况下,使用行缓冲I/O(Perl默认用于TTY的)可以减少缓冲区刷新的频率,并使程序更多地花费时间在CPU处理上。普通用户在终端或文件中不太可能注意到差异。

换句话说,如果我预计通过管道传输连续的数据流,自动刷新是有意义的,因为代码不会等待太久。我的理解正确吗? - Zaid
不,只需一次性发送所有标头即可。将它们放入行缓冲区并不重要。所有内容都会读取所有标头。 - tchrist
在每个头部换行符后刷新是否比仅在结尾的双换行符处刷新更好? - tchrist
1
一个像 User-Agent 这样的大型 HTTP header 行只有约 120 字节。短行可能小于 20 字节。使用典型的 MTU,超过 20 个 HTTP header 行应该很容易适合一个数据包。如果您将 HTTP header 行缓冲,则大多数网络堆栈将每行输出一个数据包。这会导致 TCP/IP 开销增加 20 倍。HTTP 是一个不应该被行缓冲的协议的完美示例,而 IRC 则是同样适合进行行缓冲的协议的完美示例。 - Ven'Tatsu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接