我有一个包含250+个2 GB文件的文件夹。我需要在这些文件中搜索字符串/模式并将结果输出到output
文件中。我知道我可以运行以下命令,但是它太慢了!
grep mypattern * > output
我想加快速度。作为Java的程序员,我知道多线程可以用来加快进程。我一直在研究如何以grep
“多线程模式” 启动并将输出写入单个output
文件。
我有一个包含250+个2 GB文件的文件夹。我需要在这些文件中搜索字符串/模式并将结果输出到output
文件中。我知道我可以运行以下命令,但是它太慢了!
grep mypattern * > output
我想加快速度。作为Java的程序员,我知道多线程可以用来加快进程。我一直在研究如何以grep
“多线程模式” 启动并将输出写入单个output
文件。
Answers:
有两个简单的解决方案。基本上,使用xargs
或parallel
。
xargs方法:
您可以使用xargs
具有find
如下:
find . -type f -print0 | xargs -0 -P number_of_processes grep mypattern > output
您将在其中替换number_of_processes
为要启动的最大进程数。但是,如果您的性能受到I / O的限制,则不能保证为您带来出色的性能。在这种情况下,您可以尝试启动更多进程来补偿等待I / O所浪费的时间。
此外,通过包含find,您可以指定更高级的选项,而不仅仅是文件模式,例如修改时间等。
如Stéphane的评论所解释的,这种方法的一个可能问题是,如果文件很少,则xargs
可能无法为它们启动足够多的进程。一种解决方案是使用该-n
选项xargs
来指定一次应从管道中获取多少个参数。设置-n1
将强制xargs
为每个文件启动一个新进程。如果文件很大(例如在该问题的情况下)并且文件数量相对较少,则这可能是理想的行为。但是,如果文件本身很小,则启动新进程的开销可能会破坏并行性的优势,在这种情况下,更大的-n
值会更好。因此,该-n
选项可能会根据文件大小和数量进行微调。
并行方法:
另一种方法是使用Ole Tange GNU并行工具parallel
(在此处提供)。这样可以更好地控制并行性,甚至可以分布在多个主机上(例如,如果您的目录是共享的,将是有益的)。使用并行的最简单语法为:
find . -type f | parallel -j+1 grep mypattern
如果该选项-j+1
指示并行启动一个进程,而该进程超出了计算机内核的数量(这对I / O受限任务可能会有帮助,您甚至可以尝试增加数量)。
与xargs
实际保留每个过程的输出顺序并生成连续的输出相比,并行还具有优势。例如,使用xargs
,如果进程1生成一条线说p1L1
,进程2生成一条线p2L1
,进程1生成另一条线p1L2
,则输出将是:
p1L1
p2L1
p1L2
而parallel
输出应为:
p1L1
p1L2
p2L1
这通常比xargs
输出有用。
-n
结合使用-P
。否则,xargs
如果有两个文件,则可能最终不会产生多个进程。
grep
每个文件中启动一个。除非文件很大,而且文件很少,否则您可能要增加一点,因为您将花费一些时间来启动和停止grep进程而不是在文件中进行搜索。
至少有两种方法可以加快CPU的grep速度:
如果要搜索固定字符串而不是正则表达式,请指定-F
标志;
如果您的模式仅是ASCII码,请使用8位语言环境而不是UTF-8,例如LC_ALL=C grep ...
。
如果您的硬盘成为瓶颈,这些将无济于事。在那种情况下,并行化可能也无济于事。
man grep
“直接调用中看到,因为egrep或fgrep已被弃用,但提供该历史记录是为了允许依赖它们的历史应用程序不经修改地运行。” 不确定这是否真的重要,但与grep -F
如果问题不是受I / O约束,则可以使用针对多核处理而优化的工具。
您可能想看一下sift(http://sift-tool.org,免责声明:我是该工具的作者)或白银搜索者(https://github.com/ggreer/the_silver_searcher)。
如果您使用正则表达式模式而不是简单字符串搜索,则银色搜索器的文件大小限制为2GB。