【发布时间】:2012-12-12 12:10:57
【问题描述】:
我遇到了一个奇怪的问题。我有一个大文件(可能超过 1,000,000,000 行),其中仅包含一个代表文件大小的列。好像
55568
9700
7243
9692
63
5508
1679
14072
.....
我想计算每个值的出现次数。我使用两个不同的脚本
注意::下面使用的文件被剪切,仅包含10,000行!!!
bob@bob-ruby:~$ cat 1.sh
#!/bin/bash
while read size ; do
set -- $size
((count[$1]++))
done < file-size.txt
bob@bob-ruby:~$
bob@bob-ruby:~$ cat 2.sh
#!/bin/bash
awk '{count[$1]++}' file-size.txt
bob@bob-ruby:~$
我发现 1.sh(纯 shell 脚本)比 2.sh(awk-script)慢得多
bob@bob-ruby:~$ time bash 2.sh
real 0m0.045s
user 0m0.012s
sys 0m0.032s
bob@bob-ruby:~$ time bash 1.sh
real 0m0.618s
user 0m0.508s
sys 0m0.112s
bob@bob-ruby:~$
通过 'strace' 命令,我发现 1.sh 产生了很多 syscall ,而 '2.sh' 则少得多,这是为什么呢?
那是 'awk' 在里面做一些“魔法”工作吗?
bob@bob-ruby:~$ strace -c bash 1.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
38.62 0.042011 1 30320 rt_sigprocmask
29.97 0.032597 2 20212 _llseek
15.33 0.016674 2 10115 read
12.57 0.013675 1 10106 10106 ioctl
(cut)
bob@bob-ruby:~$ strace -c bash 2.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
95.52 0.008000 4000 2 1 waitpid
3.20 0.000268 21 13 5 access
1.28 0.000107 5 21 fstat64
0.00 0.000000 0 9 read
【问题讨论】:
-
为什么这很奇怪? Shell 脚本并不以其性能而闻名(它们很慢)。
-
纯粹出于好奇,
cat file | sort | uniq -c需要什么时间? -
我读过 ABS 指南,它告诉我们尽可能少使用管道,
-
这些脚本甚至不会产生任何要检查的输出。可能是 awk 只是优化了计算
-
@favoretti,由于 OP 非常关心管道操作员,您可以通过消除 cat 的无用使用并只说
sort -n | uniq -c来节省两者之一
标签: performance bash awk while-loop