我在一个大文件上运行 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
的输出使用w
rite 命令和一个或多个命名的w
rite-file[s]。它仍然会减慢速度,但它可能会比其他选择更好。
你可以用任何sed
类似的方法来做到这一点:
sed -n 'w outfile'
sed
的w
rite 命令始终是立即的 - 它是无缓冲的输出。并且因为(默认情况下) sed
每个行周期应用一次命令,sed
即使在管道中间,也可以轻松用于有效地行缓冲 I/O。这样,至少,你可以让第二个pv
始终保持最新状态,sed
例如:
pv ... | sed -n '24629045,24629162!w /dev/fd/1' | pv ...
/dev/fd/[num]
...虽然假设有一个提供链接的系统(也就是说:几乎所有基于 Linux 的系统 - Android 除外 - 并且还有很多其他的)。如果所述链接的可用性失败,要做同样的事情,您可以显式创建自己的管道,mkfifo
并将其用作最后一个pv
的标准输入,并将其命名为sed
的w
rite 文件。