删除大型词汇表中重复项的最快方法是什么?

时间:2015-09-01 17:00:05

标签: bash sorting unix awk processing-efficiency

类似的问题是made here,但它们没有解决为什么排序 awk 之间存在速度差异的原因。

我首先在Unix Stackexchange上提出这个问题但是因为他们告诉我这对Stackoverflow来说是一个很好的问题我会在这里发布。

我需要重复删除大型词汇表。我尝试了几个命令并进行了一些研究herehere,他们解释说重复删除单词表的最快方法似乎是使用awk,因为awk没有对列表进行排序。它使用哈希查找来跟踪项目并删除重复项。由于AWK使用哈希查找,他们认为大O就像这样

  

awk - > O(n)?
  排序 - > O(n log n)?

但是我发现这不是真的。这是我的测试结果。我使用this python script生成了两个随机单词列表。

List1 = 7 Mb
List2 = 690 Mb

测试命令

sort -u input.txt -o output.txt 

awk '!x[$0]++' input.txt > output.txt

结果AWK:
的List1
真正的0m1.643s
用户0m1.565s
sys 0m0.062s

列表2
真正的2m6.918s
用户2m4.499s
sys 0m1.345s

结果排序:
的List1
真实0m0.724s
用户0m0.666s
sys 0m0.048s

列表2
真实1m27.254s
用户1m25.013s
sys 0m1.251s

我一遍又一遍地进行这些测试,并找到了一致的结果。也就是说,SORT快得多。有人可以解释为什么以及是否有更快的方法来做到这一点?

************更新***********
可能导致我的结果有缺陷的事情

  1. 缓存:我通过更改顺序排除了这种可能性 执行测试
  2. 大O符号的常数因素。我认为由于单词列表的大小,它们在这一点上应该变得无关紧要。 (600MB)
  3. 算法执行不当:这仍然是我没有检查过awk和sort的源代码的可能性

2 个答案:

答案 0 :(得分:3)

您的示例输入具有重复值的批次;您在样本数量100,000,000中只有1,000,000个不同的值,因此您只希望1%的值是唯一的。我并不确切知道sort -u是如何工作的,但想象它是一种合并排序,可在每次合并期间过滤唯一值。那么有效输入大小将远小于100,000,000。仅使用1,000,000个值重新运行命令,但从500,000个不同的值中选择(因此50%,而不是1%,预计是唯一的)会产生以下结果:

% time awk '!x[$0]++' randomwordlist.txt > /dev/null
awk ...  1.32s user 0.02s system 99% cpu 1.338 total
% time sort -u randomwordlist.txt -o /dev/null
sort ...  14.25s user 0.04s system 99% cpu 14.304 total

答案 1 :(得分:1)

  1. big-O表示法仅告诉您某些N ,其中O( N )将比O快( N * log N < / em>的)。实际操作次数包括常数因子和附加项,因此实际上数字为○( N )〜 k1 * N + c1
    O( N * log N )〜 k2 * N * log(N)+ c2
    对于所选择的N,哪一个更快 取决于 k c 的值。
  2. 某些输入/算法组合会导致非常小的 k c
  3. 任何一个程序都不能使用最佳算法。
  4. 缓存效果?如果您始终在测试2之前运行测试1,则第二个测试可能使用已缓存的数据,而第一个测试始终必须从头开始加载。正确消除/确定缓存效果是一门艺术。
  5. 我没有想到的其他东西,其他人会很快指出: - )