Si vous voulez de la vitesse réelle:
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;
Est un pseudo-one-liner incroyablement rapide.
Un simple test montre que sur mon CPU Core i7 870 à 2,93 GHz, elle compte à peine plus de 600 Mo / 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
Contrairement aux solutions impliquant le tri, celle-ci fonctionne en mémoire constante (4K), ce qui est très utile si votre fichier est beaucoup plus volumineux que votre RAM.
Et, bien sûr, avec un peu de graisse pour coude, nous pouvons gagner 0,7 seconde:
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;
Filets juste au-dessus de 1,1 Go / s en finition en:
real 0m0.943s
user 0m0.798s
sys 0m0.134s
À titre de comparaison, j’ai testé certaines des autres solutions de cette page qui semblaient prometteuses.
La sed
/ awk
solution a fait un vaillant effort, mais il est mort au bout de 30 secondes. Avec une expression aussi simple, je m'attends à ce que ce soit un bogue dans sed (version 4.2.1 de GNU sed):
$ 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
La méthode perl semblait également prometteuse, mais j’ai abandonné après 7 minutes d’exécution.
time perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c' < bigdna
^C
real 7m44.161s
user 4m53.941s
sys 2m35.593s