我只是想指出uniq,即使在排序列表上,gnu 似乎也非常慢。
我只是尝试从排序的文件名列表中获取目录前缀列表:
$ pv all_files|cut-d'/'-f1,2,3,4|uniq>all_prefixes36.7GiB0:07:41[81.4MiB/s]$ pv all_files|cut-d'/'-f1,2,3,4|sort-u>all_prefixes236.7GiB0:03:14[193MiB/s]$ pv all_files|cut-d'/'-f1,2,3,4|awk'!x[$0]++'>all_prefixes336.7GiB0: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/null339.24user3.54system1:28.87elapsed385%CPU(0avgtext+0avgdata2365856maxresident)k9555544inputs+0outputs(0major+591298minor)pagefaults0swaps$ time awk'!x[$0]++'test>/dev/null51.15user1.55system0:52.94elapsed99%CPU(0avgtext+0avgdata10976maxresident)k0inputs+0outputs(0major+1923minor)pagefaults0swaps$ time uniq test>/dev/null421.89user2.76system7:06.63elapsed99%CPU(0avgtext+0avgdata1980maxresident)k52712inputs+0outputs(0major+79minor)pagefaults0swaps
因此,看来您的awk解决方案是这3种解决方案中最快的,并且实际上使用的内存最少
update2
,现在具有更简单的语言环境
$exportLC_ALL=c$ time sort-u test>/dev/null1.2m?TueApr2117:09:222020119.18user3.64system0:38.24elapsed321%CPU(0avgtext+0avgdata2013472maxresident)k$ time awk'!x[$0]++'test>/dev/null1161ms?TueApr2117:07:31202067.23user2.50system1:10.16elapsed99%CPU(0avgtext+0avgdata10480maxresident)k7187520inputs+0outputs(0major+1912minor)pagefaults0swaps$ time uniq test>/dev/null22.05user2.02system0:24.24elapsed99%CPU(0avgtext+0avgdata1488maxresident)k2959648inputs+0outputs(1major+72minor)pagefaults0swaps
这次uniq确实赢得了比赛 ...正如StéphaneChazelas在评论中暗示的那样,将您的语言环境设置为C可以使sort和uniq更快!