wc -l 的性能

Performance of wc -l

我运行以下命令:

time for i in {1..100}; do find / -name "*.service" | wc -l; done

然后得到了 100 行结果:

实数 0m35.466s 用户 0m15.688s 系统 0m14.552s

我然后运行下面的命令:

time for i in {1..100}; do find / -name "*.service" | awk 'END{print NR}'; done

然后得到了 100 行结果:

实际 0m35.036s 用户 0m15.848s 系统 0m14.056s

我准确地说我已经 运行 find / -name "*.service" 就在之前所以它被缓存用于两个命令。

我预计 wc -l 会更快。为什么不是?

三件事:

  1. 这么小的差异通常并不显着:

    0m35.466s - 0m35.036s = 0m0.43s  or 1.2%
    
  2. 然而 wc -l awk 'END{print NR}' 快 (10 倍)。

    % time seq 100000000  | awk 'END{print NR}' > /dev/null
    
    real    0m13.624s
    user    0m14.656s
    sys 0m1.047s
    % time seq 100000000  | wc -l > /dev/null
    
    real    0m1.604s
    user    0m2.413s
    sys 0m0.623s
    
  3. 我的猜测是硬盘缓存保存了 find 结果,因此在第一个 运行 和 wc -l 之后,[=] 所需的大部分读取=14=] 在缓存中。据推测,初始 find 磁盘读取和第二个 find 缓存读取之间的时间差异将大于 awk 和 [=] 之间的 运行 时间差异20=].

    测试这个的一种方法是重新启动,这会清除硬盘缓存,然后 运行 再次进行这两个测试,但是 顺序相反 ,这样awk 首先是 运行。我希望第一个-运行 awk 比第一个-运行 wc 和第二个-运行 [=20= 还要慢] 会比第二个-运行 awk 快。

其他人已经提到您可能会选择 find,而不是 wcawk。不过,wcawk 之间可能存在各种有趣的差异,有待探索。

这是我得到的结果:

Mac OS 10.10.5 awk    0.16m lines/second
GNU awk/gawk 4.1.4    4.4m  lines/second
Mac OS 10.10.5 wc     6.8m  lines/second
GNU wc 8.27          11m    lines/second

我没有使用 find,而是在循环中对大型文本文件(66k 行)使用了 wc -l 或 `awk 'END{print NR}'。

我改变了命令的顺序,但没有发现任何大到足以改变我报告的排名的偏差。

LC_CTYPE=C 对这些中的任何一个都没有可衡量的影响。

结论

  1. 不要使用 mac 内置命令行工具,除非数据量很小。

  2. GNU wc 在计算行数方面比 GNU awk 快。

我使用 MacPorts GNU 二进制文件。看看 Homebrew 二进制文件如何比较会很有趣。 (我猜他们会输。)