为什么 sed 在写入输出后不立即退出?

为什么 sed 在写入输出后不立即退出?

我在一个大文件上运行 sed,并使用光伏发电实用程序来查看读取输入和写入输出的速度。虽然 pv 显示 sed 在大约 5 秒内读取输入并写入输出,但 sed 在另外 20-30 秒内没有退出。为什么是这样?

这是我看到的输出:

pv -cN source input.txt | sed "24629045,24629162d" | pv -cN output > output.txt
   source: 2.34GB 0:00:06 [ 388MB/s] [==========================================================================================================>] 100%            
   output: 2.34GB 0:00:05 [ 401MB/s] [              <=>                                                                                                           ]

答案1

有两个原因。首先,你没有告诉它q

考虑:

seq 10 | sed -ne1,5p

在这种情况下,虽然它只p打印输入行的前半部分,但它仍然必须读取其余的输入行直到 EOF。反而:

seq 10|sed 5q

它会立即退出那里。

您还需要处理每个进程之间的延迟。因此,如果pv以 4kb 缓冲,并且sed缓冲 4kb,那么最后一个pv始终落后于输入 8kb。这个数字很可能比这个数字还要高。

你可以尝试-u使用 GNU/BSD/AST 进行切换,sed但这几乎是肯定的不是将有助于提高大输入的性能。如果你用sed它来调用 GNU,-u它将read()针对输入的每个字节。我没有看过其他人在这种情况下会做什么,但我没有理由相信他们会做任何不同的事情。所有三个文件的-u含义无缓冲的- 对于流而言,这是一个非常普遍理解的概念。

您可能做的另一件事是显式 line-buffersed输出使用write 命令和一个或多个命名的write-file[s]。它仍然会减慢速度,但它可能会比其他选择更好。

你可以用任何sed类似的方法来做到这一点:

sed -n 'w outfile'

sedwrite 命令始终是立即的 - 它是无缓冲的输出。并且因为(默认情况下) sed每个行周期应用一次命令,sed即使在管道中间,也可以轻松用于有效地行缓冲 I/O。这样,至少,你可以让第二个pv始终保持最新状态,sed例如:

pv ... | sed -n '24629045,24629162!w /dev/fd/1' | pv ...

/dev/fd/[num]...虽然假设有一个提供链接的系统(也就是说:几乎所有基于 Linux 的系统 - Android 除外 - 并且还有很多其他的。如果所述链接的可用性失败,要做同样的事情,您可以显式创建自己的管道,mkfifo并将其用作最后一个pv的标准输入,并将其命名为sedwrite 文件。

相关内容