如果您想要一些真实的速度:
echo 'int cache[256],x,y;char buf[4096],letters[]="tacgn-"; int main(){while((x=read(0,buf,sizeof buf))>0)for(y=0;y<x;y++)cache[(unsigned char)buf[y]]++;for(x=0;x<sizeof letters-1;x++)printf("%c: %d\n",letters[x],cache[letters[x]]);}' | gcc -w -xc -; ./a.out < file; rm a.out;
是一个非常快的伪一线客机。
一个简单的测试显示,在我的Core i7 CPU 870 @ 2.93GHz上,它的计数刚好超过600MB / s:
$ du -h bigdna
1.1G bigdna
time ./a.out < bigdna
t: 178977308
a: 178958411
c: 178958823
g: 178947772
n: 178959673
-: 178939837
real 0m1.718s
user 0m1.539s
sys 0m0.171s
与涉及排序的解决方案不同,此解决方案在恒定(4K)内存中运行,如果您的文件远大于ram,这将非常有用。
而且,当然,使用少量的肘部润滑脂,我们可以剃掉0.7秒:
echo 'int cache[256],x,buf[4096],*bp,*ep;char letters[]="tacgn-"; int main(){while((ep=buf+(read(0,buf,sizeof buf)/sizeof(int)))>buf)for(bp=buf;bp<ep;bp++){cache[(*bp)&0xff]++;cache[(*bp>>8)&0xff]++;cache[(*bp>>16)&0xff]++;cache[(*bp>>24)&0xff]++;}for(x=0;x<sizeof letters-1;x++)printf("%c: %d\n",letters[x],cache[letters[x]]);}' | gcc -O2 -xc -; ./a.out < file; rm a.out;
刚超过1.1GB / s的网完成速度:
real 0m0.943s
user 0m0.798s
sys 0m0.134s
为了进行比较,我在本页上测试了其他一些解决方案,这些解决方案似乎具有一定的速度保证。
将sed
/ awk
解决方案做出了勇敢的努力,但30秒后死亡。有了这样一个简单的正则表达式,我希望这是sed(GNU sed版本4.2.1)中的错误:
$ time sed 's/./&\n/g' bigdna | awk '!/^$/{a[$0]++}END{for (i in a)print i,a[i];}'
sed: couldn't re-allocate memory
real 0m31.326s
user 0m21.696s
sys 0m2.111s
perl方法似乎也很有希望,但是我在运行了7分钟后就放弃了
time perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c' < bigdna
^C
real 7m44.161s
user 4m53.941s
sys 2m35.593s