perdita di memoria awk?


11

Sulla base di questo sto eseguendo il comando

< /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

Ho notato che la memoria utilizzata da awk cresce continuamente mentre questo comando è in esecuzione, ad esempio consumando oltre 500 MB di memoria quando sono stati riprodotti 75 MB di dati audio non elaborati. Tutti gli altri comandi nella pipeline mantengono una quantità costante di memoria.

A cosa serve awk questa memoria e esiste un'alternativa che elabora lo streaming previsto usando solo una quantità costante di memoria?


nel caso in cui la versione di awk sia importante:

 awk --version
awk version 20070501

Ecco il comando che ho testato in base alla risposta di 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

Vedo anche una perdita di memoria sul mio sistema BSD-Darwin (Mac).
Otheus

Hai detto Here's the command I tested...ma hai dimenticato di dirci il risultato di quel test - ha risolto il problema o no? Potrebbe non a[]esserlo dal momento che ogni riferimento a un elemento nel ciclo creerebbe voci se non esistessero, quindi in caso contrario - aiuta se si cancella esplicitamente l'array prima della divisione o dopo averlo usato, ad esempio 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)) }'? Con quel segmento di codice devi lasciare la divisione () nella sua posizione originale, non spostarla su INIZIA.
Ed Morton,

Risposte:


11

Questa affermazione è strana:

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

Suddivide ripetutamente una stringa costante per creare un array a. Se lo sposti in una BEGINsezione, il programma dovrebbe funzionare allo stesso modo, senza allocare una nuova copia adell'array per ciascun record di input.

Affrontare i commenti: for-loop ed espressione non allocano la memoria in modo semplice. Un rapido confronto tra mawk, gawk e awk mostra che non ci sono problemi con i primi due, ma /usr/bin/awksu OSX perde rapidamente. Se Apple avesse un sistema di segnalazione bug, quello sarebbe il posto dove andare.


1
Ho fatto come mi hai suggerito sul mio Mac (non sono l'OP). Vedo ancora una perdita di memoria con awk.
Otheus

In qualche modo, è sufficiente fare riferimento alla una memoria di hash usi.
Otheus

Anch'io; Vedo ancora la crescita della memoria. Ho anche fatto un confronto approssimativo e l'utilizzo della memoria sembra crescere allo stesso ritmo con questo cambiamento.
bames53

Anche questo causerà una perdita di memoria:awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,","); } { for (i = 0; i < 1; i+= 0.0001) a[1]; }'
Otheus

Potresti passare a mawk o gawk. Il sistema base di Apple include alcuni pezzi d'antiquariato reali.
Thomas Dickey,

5

Ecco un equivalente perl che non perde:

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) }'

È quasi identico. $1viene sostituito da $F[0]e iviene sostituito da $i. L'hash aviene sostituito con una matrice reale, @a.

Sarebbe saggio generare alcuni input e confrontare le differenze di output e note tra i due. Ci sono spesso sfumature su come i linguaggi interpretativi affrontano il virgola mobile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.