Perl / xargs使用xargs -n1 / -i表现糟糕

问题描述 投票:1回答:2

我写了一个小小的perl单行:

find . -name '*.cpp' -print0 2>/dev/null | xargs -0 -i perl -ne 'if (/\+\+\S*[cC]ursor\S*/ && !/[!=]=\s*DB_NULL_CURSOR/) {print "$ARGV:$.\n $_\n";}' {}

在我正在运行的目录中,find部分返回5802个结果。

现在,我理解xargs -i(或-n1)会对性能产生影响,但是使用-i

find . -name '*.cpp' -print0 2> /dev/null  0.33s user 1.12s system 0% cpu 3:12.57 total
xargs -0 -i perl -ne  {}  4.12s user 32.80s system 16% cpu 3:42.22 total

没有:

find . -name '*.cpp' -print0 2> /dev/null  0.27s user 1.22s system 95% cpu 1.556 total
xargs -0 perl -ne   0.62s user 0.69s system 61% cpu 2.117 total

分钟与几秒钟(测试的顺序确定无关紧要)。除了在第二种情况下显然不正确的行号之外,实际的perl结果是相同的。

Cygwin / bash / perl5v26和WSL Ubuntu 16.04 / zsh / perl5v22中的行为相同。两种情况下文件系统都是NTFS。但是......我有点假设我写的小单行必须有一些错误,那些东西是无关紧要的?

编辑:我发现在启动时使用-f禁用sitecustomize.pl - 我隐约记得用perl --help看到的选项 - 可能会有所帮助。它没。此外,我知道由于perl编译正则表达式,-i的性能影响将会很大。这似乎仍然失控。

perl xargs
2个回答
1
投票

xargs将为它处理的每一行调用一个新进程,因此在你的情况下,它将会旋转5802次,并在系列中执行此操作

你可以试试parallel

您可能正在使用xargs为每行输入调用计算密集型命令。如果xargs允许您利用机器中的多个核心,那不是很好吗?这就是-P的用途。它允许xargs并行多次调用指定的命令。例如,您可以使用它来并行运行多个ffmpeg编码。不过,我只想向您展示另一个人为的例子。

或者另一方面,你可以使用更轻的旋转的sed


0
投票

好吧,我的根本误解是假设最大命令行长度在2000范围内。所以我假设每20个文件左右一个perl实例(每个大约120个字符)。这非常不正确。

getconf ARG_MAX显示实际可接受的长度。就我而言:

2097152

所以,我正在研究1个perl实例与5802个实例。我能想到的唯一的perl解决方案是删除-n并手动实现循环,显式关闭每个文件。

我认为更好的解决方案是awk:

 find . -name '*.cpp' 2>/dev/null -print0 | xargs -0 awk '{if (/\+\+\S*[cC]ursor\S*/ && !/[!=]=\s*DB_NULL_CURSOR/) {print FILENAME ":" FNR "  " $0}}'

或者grep:

find . -name '*.cpp' 2>/dev/null -print0 | xargs -0 grep -nE '\+\+\S*[cC]ursor\S*' | grep -v '[!=]=\s*DB_NULL_CURSOR'

两者都在2或3秒范围内执行。

© www.soinside.com 2019 - 2024. All rights reserved.