Jika Anda menginginkan kecepatan nyata:
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;
Adalah pseudo-one-liner yang sangat cepat.
Sebuah tes sederhana menunjukkan bahwa pada Core i7 CPU 870 @ 2.93GHz saya menghitung lebih dari 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
Tidak seperti solusi yang melibatkan penyortiran, yang ini berjalan dalam memori konstan (4K), yang sangat berguna, jika file Anda jauh lebih besar daripada ram Anda.
Dan, tentu saja dengan sedikit minyak siku, kita dapat mencukur 0,7 detik:
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;
Jaring lebih dari 1,1GB / detik finishing di:
real 0m0.943s
user 0m0.798s
sys 0m0.134s
Sebagai perbandingan, saya menguji beberapa solusi lain pada halaman ini yang tampaknya memiliki semacam janji kecepatan.
The sed
/ awk
solusi membuat usaha gagah berani, namun meninggal setelah 30 detik. Dengan regex yang sederhana, saya berharap ini menjadi bug in sed (GNU sed versi 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
Metode perl juga tampak menjanjikan, tetapi saya menyerah setelah menjalankannya selama 7 menit
time perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c' < bigdna
^C
real 7m44.161s
user 4m53.941s
sys 2m35.593s