Nếu bạn muốn một số tốc độ thực sự:
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;
Là một giả giả cực kỳ nhanh chóng.
Một thử nghiệm đơn giản cho thấy trên CPU Core i7 870 @ 2,93 GHz của tôi, nó chỉ đạt hơn 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
Không giống như các giải pháp liên quan đến sắp xếp, cái này chạy trong bộ nhớ (4K) không đổi, rất hữu ích, nếu tệp của bạn lớn hơn nhiều so với ram của bạn.
Và, tất nhiên với một chút mỡ khuỷu tay, chúng ta có thể cạo sạch 0,7 giây:
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;
Lưới chỉ hơn 1,1 GB / giây hoàn thiện trong:
real 0m0.943s
user 0m0.798s
sys 0m0.134s
Để so sánh, tôi đã thử nghiệm một số giải pháp khác trên trang này dường như có một số lời hứa tốc độ.
Các sed
/ awk
giải pháp thực hiện một nỗ lực dũng cảm, nhưng đã chết sau 30 giây. Với một regex đơn giản như vậy, tôi hy vọng đây là một lỗi trong sed (GNU sed phiên bản 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
Phương pháp perl có vẻ đầy hứa hẹn, nhưng tôi đã từ bỏ sau khi chạy nó trong 7 phút
time perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c' < bigdna
^C
real 7m44.161s
user 4m53.941s
sys 2m35.593s