Tee 会减慢管道速度吗?

Tee 会减慢管道速度吗?

我想知道 tee 是否会减慢管道速度。毕竟,将数据写入磁盘比通过管道传送数据要慢。

tee 是否会等待将数据发送到下一个管道,直到数据写入磁盘? (如果没有,我猜 tee 必须对已发送但未写入磁盘的数据进行排队,这对我来说听起来不太可能。)

$ program1 input.txt | tee intermediate-file.txt | program2 ...

答案1

是的,它会减慢速度。它基本上确实有一个未写入数据的队列,尽管这实际上是由内核维护的——所有程序都有这个队列,除非它们明确提出其他要求。

例如,这是一个使用 的简单管道pv,这很好,因为它显示传输速率:

$ pv -s 50g -S -pteba /dev/zero | cat > /dev/null 
  50GiB 0:00:09 [ 5.4GiB/s] [===============================================>] 100%

现在,让我们tee在其中添加一个,甚至不需要编写额外的副本 - 只需将其转发即可:

$ pv -s 50g -S -pteba /dev/zero | tee | cat > /dev/null 
  50GiB 0:00:20 [2.44GiB/s] [===============================================>] 100%            

所以,这有点慢,而且它甚至没有做任何事情!这是 tee 内部将 STDIN 复制到 STDOUT 的开销。 (有趣的是,pv在其中添加第二个仍保持在 5.19GiB/s,因此pvtee.pv使用快得多splice(2)tee但可能不会。)

不管怎样,让我们​​看看如果我告诉tee写入磁盘上的文件会发生什么。它开始时相当快(约 800MiB/s),但随着时间的推移,它会不断减慢,最终降至约 100MiB/s,这基本上是磁盘写入带宽的 100%。 (快速启动是由于内核缓存了磁盘写入,而磁盘写入速度减慢是内核拒绝让缓存无限增长。)

有关系吗?

以上是最坏的情况。上面使用管道尽可能快地喷出数据。我能想到的唯一现实世界的用途是将原始 YUV 数据传输到/从ffmpeg.

当您以较慢的速率发送数据时(因为您正在处理它们等),其影响将会小得多。

答案2

毕竟这里没什么奇怪的

>POSIX 说,

描述

球座实用程序应将标准输入复制到标准输出,在零个或多个文件中进行复制。球座实用程序不应缓冲输出。

还有那个

基本原理

缓冲要求意味着 tee 不允许使用 ISO C 标准完全缓冲或行缓冲写入。这并不意味着 tee 必须先执行 1 字节读取,然后执行 1 字节写入。

因此,在不解释“基本原理”的情况下,tee可能只会读取和写入不管多少字节一次可以放入管道缓冲区,在每次写入时刷新输出。

是的,根据应用程序的不同,这可能效率相当低——所以请随意删除/注释掉其中的任何一个:
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L208
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L224

相关内容