Linux中最快的`uniq`工具


8

我的文本文件很大(1.5 G),

我想知道Linux中最快,更可靠的工具是什么。

我通常使用:

awk '!x[$0]++' file.txt

但是当我使用htop命令时,我看到我的内存使用量正在增加。

我想知道什么是处理大型文件最快,更可靠的方法。

uniq?
sort?
sed?
awk?

为什么?


您是否尝试过运行它们time
choroba

时间很重要,内存使用和可靠性也很重要(我的意思是准确地完成了他的工作)
MLSC 2014年

尚未...但是我之前做过一些测试...然后问一个地方,有人告诉我awk是最好的..但是在htop中...我看到内存使用率正在增加
MLSC 2014年

3
@MortezaLSC:这是一个权衡。程序越快,使用的内存就越多。
cuonglm

Answers:


16

让我们考虑每个解决方案的工作方式。

  • uniq这要求文件已被排序。如果不是,则必须sort先将其通过管道传输,这意味着sort必须将整个文件读入内存,对其重新排序(O(n log n)),然后将其写入管道。的工作uniq非常便宜,因为它只需要比较其输入的相邻行。

  • sort -u这结合了的工作sort | uniq。这必须像awk脚本一样将所有唯一的输入收集到内存中,但是在生成输出之前,还要浪费时间对它们进行排序。这是O(n log n),尽管在这种情况下n是唯一项目的数量,而不是所有输入。因此,它比管道更好。

  • sed我不确定您为什么列出此内容,因为我根本想不出一种很好的方法来完成此操作sed。也许,如果您首先对其进行排序并通过管道传递给sed脚本,那么就有一种比较相邻行的方法。因此,sed将只做某事uniq,并且uniq可能会尽可能高效地完成它。

  • awk这可能是最好的,因为它仅执行最少的工作量。在读取每一行时,它会进行有效的哈希查找,以查看该行是否已在其内存中,并且仅将唯一行存储为哈希键,并将计数器存储为值。(如果该行以前不存在,则条件为true,因此将打印该行。否则将不会打印。)这会占用O(n)时间和O(uniq n)内存。

每种方法都将使用大量内存,用于对输入进行排序或跟踪已看到的输入,以便删除重复项。


1
+1关于的解释awk还解释了为什么它使用越来越多的内存。任何进行排序的操作最终也会执行此操作,只有1)它可能会一次全部使用,2)它可能会使用更多,这取决于唯一键与重复键的数量。
goldilocks 2014年

@Barmar请原谅,但是当我有一个大文件(16 G),内存容量为8G时,那么我的内存将如何处理?
MLSC 2014年

8
@goldilocks,sort以一种智能的方式求助于临时文件,以避免填满内存。它的内存使用率是有约束的。该边界可通过某种实现方式进行自定义。让系统将内存随机交换到磁盘(这也会影响系统上的应用程序),效率更高。
斯特凡Chazelas

确实如此。因此,如果遇到awk内存不足的情况,则sort可能是唯一的解决方案,因为它已被设计用来处理此问题。另一方面,所有磁盘读取和写入操作都会减慢其速度,因此可能需要很长时间才能完成。如果要处理大量数据,则可能应该使用DBMS而不是文本文件。
2014年

@Barmar您如何推断重新排序的时间增加O(n log n)?还是您从其他地方知道?
jimmij 2014年


0

我只是想指出uniq,即使在排序列表上,gnu 似乎也非常慢。

我只是尝试从排序的文件名列表中获取目录前缀列表:

$ pv all_files | cut -d '/' -f 1,2,3,4 | uniq > all_prefixes

36.7GiB 0:07:41 [81.4MiB/s]

$ pv all_files | cut -d '/' -f 1,2,3,4 | sort -u > all_prefixes2

36.7GiB 0:03:14 [ 193MiB/s]

$ pv all_files  | cut -d '/' -f 1,2,3,4 | awk '!x[$0]++' > all_prefixes3                                        
36.7GiB 0:02:18 [ 270MiB/s] 

sort -u似乎是uniq的两倍,这是从stdin读取并写入stdout的排序,所以我还没有看到它进行任何并行化。我不知道为什么uniq应该这么慢然后排序,因为它不必对列表进行排序...

该命令的输出非常小(有很多重复项),只有264kb,并且pv完成后排序会立即终止。

如果改变命令的顺序,速度将保持不变,我的流量在这里受CPU时间的限制,而不是磁盘访问和缓存的限制(我只有8GB的RAM,未使用交换空间)

我在具有gnu coreutils sort和uniq和gnu awk的fedora 31机器上运行该代码;语言环境设置为en_US.UTF-8

UPDATE,因为这引起了我的极大兴趣,所以我进行了一些更多的测试,让我们将剪切的部分排除在外,并确保文件排序正确

cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test

这需要8.4分钟。测试现在是7.9GB大

让我们在文件上而不是在管道上运行这些工具,这将允许这些工具做更多的优化,例如sort将是多线程的。以及更快的ssd。

您可能不会注意到排序也占用了大量内存,因为它会对/ tmp中的临时文件(可能是tmpfs并在您的ram中)进行巧妙的欺骗(尝试对大于/ tmp的文件进行排序,您会遇到空间问题问题,这就是为什么我需要上述命令中的-T。标志)

$ time sort -u test > /dev/null
339.24user 3.54system 1:28.87elapsed 385%CPU (0avgtext+0avgdata 2365856maxresident)k
9555544inputs+0outputs (0major+591298minor)pagefaults 0swaps

$ time awk '!x[$0]++' test > /dev/null                                                                                                                             
51.15user 1.55system 0:52.94elapsed 99%CPU (0avgtext+0avgdata 10976maxresident)k
0inputs+0outputs (0major+1923minor)pagefaults 0swaps

$ time uniq test > /dev/null                                                                                                                                  
421.89user 2.76system 7:06.63elapsed 99%CPU (0avgtext+0avgdata 1980maxresident)k
52712inputs+0outputs (0major+79minor)pagefaults 0swaps

因此,看来您的awk解决方案是这3种解决方案中最快的,并且实际上使用的内存最少

update2 ,现在具有更简单的语言环境

$ export LC_ALL=c
$ time sort -u test > /dev/null                                                                                                                                             1.2m ? Tue Apr 21 17:09:22 2020
119.18user 3.64system 0:38.24elapsed 321%CPU (0avgtext+0avgdata 2013472maxresident)k

$ time awk '!x[$0]++' test > /dev/null                                                                                                                                1161ms ? Tue Apr 21 17:07:31 2020
67.23user 2.50system 1:10.16elapsed 99%CPU (0avgtext+0avgdata 10480maxresident)k
7187520inputs+0outputs (0major+1912minor)pagefaults 0swaps

$ time uniq test > /dev/null                                                                                                                                               
22.05user 2.02system 0:24.24elapsed 99%CPU (0avgtext+0avgdata 1488maxresident)k
2959648inputs+0outputs (1major+72minor)pagefaults 0swaps

这次uniq确实赢得了比赛 ...正如StéphaneChazelas在评论中暗示的那样,将您的语言环境设置为C可以使sort和uniq更快!


sort和执行什么uniq?什么地区?
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.