fuite de mémoire awk?

11

Sur cette base, j'exécute la commande

< /dev/urandom hexdump -v -e '/1 "%u\n"' |
awk '{ split("0,2,4,5,7,9,11,12",a,",");
       for (i = 0; i < 1; i+= 0.0001)
         printf("%08X\n", 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i)) }' |
xxd -r -p |
sox -traw -r44100 -b16 -e unsigned-integer - -tcoreaudio

Je remarque que la mémoire utilisée par awk augmente continuellement pendant l'exécution de cette commande, par exemple en consommant plus de 500 Mo de mémoire au moment où 75 Mo de données audio brutes ont été lues. Toutes les autres commandes du pipeline conservent une quantité de mémoire constante.

À quoi sert awk cette mémoire et existe-t-il une alternative qui fait le traitement de flux prévu en utilisant uniquement une quantité constante de mémoire?


au cas où la version awk compte:

 awk --version
awk version 20070501

Voici la commande que j'ai testée sur la base de la réponse de Thomas Dickey:

< /dev/urandom hexdump -v -e '/1 "%u\n"' |
awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,",") }
           { for (i = 0; i < 1; i+= 0.0001)
               printf("%08X\n", 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i)) }' |
xxd -r -p |
sox -traw -r44100 -b16 -e unsigned-integer - -tcoreaudio
bames53
la source
Je constate également une fuite de mémoire sur mon système BSD-Darwin (Mac).
Otheus
Vous avez dit Here's the command I tested...mais vous avez oublié de nous dire le résultat de ces tests - cela a-t-il résolu le problème ou non? Ce n'est peut-être pas le cas, car chaque référence à un élément dans a[]la boucle créerait des entrées si elles n'existaient pas, si ce n'est pas le cas - cela aide-t-il si vous supprimez explicitement le tableau avant de le fractionner ou après l'avoir utilisé, par exemple awk '{ delete a; split("0,2,4,5,7,9,11,12",a,","); for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1 % 8]/12)*log(2))*i)) }'? Avec ce segment de code, vous devez laisser le split () à son emplacement d'origine, pas le déplacer vers BEGIN.
Ed Morton

Réponses:

11

Cette déclaration est étrange:

split("0,2,4,5,7,9,11,12",a,",");

Il fractionne de manière répétitive une chaîne constante pour créer un tableau a. Si vous déplacez cela dans une BEGINsection, le programme devrait fonctionner de la même manière - sans allouer une nouvelle copie du atableau pour chaque enregistrement d'entrée.

Adressage des commentaires: la boucle for et l'expression n'allouent pas la mémoire de manière simple. Une comparaison rapide de mawk, gawk et awk montre qu'il n'y a pas de problème avec les deux premiers, mais /usr/bin/awksur OSX fuit rapidement. Si Apple avait un système de rapport de bogues, ce serait l'endroit où aller.

Thomas Dickey
la source
1
J'ai fait comme vous l'avez suggéré sur mon Mac (je ne suis pas l'OP). Je vois toujours une fuite de mémoire avec awk.
Otheus
D'une certaine façon, il suffit de référencer l' un hachage utilise la mémoire.
Otheus
Pareil ici; Je vois toujours la croissance de la mémoire. J'ai également fait une comparaison approximative et l'utilisation de la mémoire semble augmenter au même rythme avec ce changement.
bames53
Même cela entraînera une fuite de mémoire:awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,","); } { for (i = 0; i < 1; i+= 0.0001) a[1]; }'
Otheus
Vous pouvez passer à mawk ou gawk. Le système de base d'Apple comprend de véritables antiquités.
Thomas Dickey
5

Voici un équivalent perl qui ne fuit pas:

perl -lne 'BEGIN { @a=(0,2,4,5,7,9,11,12);}
   for ($i = 0; $i < 1; $i+= 0.0001) {
     printf("%08X\n", 100*sin(1382*exp($a[$F[0] % 8]/12)*log(2))*$i) }'

C'est presque identique. $1est remplacé par $F[0]et iest remplacé par $i. Le hachage aest remplacé par un tableau réel, @a.

Il serait sage de générer une entrée et de comparer la sortie et de noter les différences entre les deux. Il existe souvent des nuances quant à la manière dont les langages d'interprétation traitent la virgule flottante.

Otheus
la source