awk fuga de memoria?

11

Base en esto , estoy ejecutando el 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

Noté que la memoria utilizada por awk crece continuamente mientras se ejecuta este comando, por ejemplo, consumiendo más de 500 MB de memoria para cuando se han reproducido 75 MB de datos de audio sin formato. Todos los otros comandos en la tubería mantienen una cantidad constante de memoria.

¿Para qué sirve awk usar esta memoria? ¿Existe alguna alternativa que procese el flujo previsto utilizando solo una cantidad constante de memoria?


en caso de que la versión awk importe:

 awk --version
awk version 20070501

Aquí está el comando que probé basado en la respuesta 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
fuente
También veo una pérdida de memoria en mi sistema BSD-Darwin (Mac).
Oteo
Usted dijo Here's the command I tested...pero olvidó decirnos el resultado de esa prueba: ¿resolvió el problema o no? Puede que no, ya que cada referencia a un elemento en a[]el bucle crearía entradas si no existieran, de lo contrario, ¿ayuda si elimina explícitamente la matriz antes de dividirla o después de usarla, por ejemplo 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 ese segmento de código, debe dejar el split () en su ubicación original, no moverlo a BEGIN.
Ed Morton

Respuestas:

11

Esta afirmación es extraña:

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

Divide repetidamente una cadena constante para crear una matriz a. Si mueve eso a una BEGINsección, el programa debería funcionar igual, sin asignar una nueva copia de la amatriz para cada registro de entrada.

Comentarios de direccionamiento: el for-loop y la expresión no asignan memoria de manera simple. Una comparación rápida de mawk, gawk y awk muestra que no hay ningún problema con los dos primeros, pero /usr/bin/awken OSX se filtra rápidamente. Si Apple tuviera un sistema de informe de errores, ese sería el lugar para ir.

Thomas Dickey
fuente
1
Hice lo que me sugirió en mi Mac (no soy el OP). Todavía veo una pérdida de memoria con awk.
Oteo
De alguna manera, sólo tiene que hacer referencia a la una memoria usos de patata.
Oteo
Igual que aquí; Todavía veo el crecimiento de la memoria. También hice una comparación aproximada y el uso de memoria parece estar creciendo al mismo ritmo con este cambio.
bames53
Incluso esto causará una pérdida de memoria:awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,","); } { for (i = 0; i < 1; i+= 0.0001) a[1]; }'
Otheus
Podrías cambiar a mawk o gawk. El sistema base de Apple incluye algunas antigüedades reales.
Thomas Dickey
5

Aquí hay un equivalente perl que no se filtra:

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

Es casi idéntico $1se reemplaza por $F[0]y ise reemplaza por $i. El hash aes reemplazada con una matriz real, @a.

Sería aconsejable generar algo de entrada y comparar la salida y observar las diferencias entre los dos. A menudo hay matices en cuanto a cómo los lenguajes interpretativos tratan el punto flotante.

Oteo
fuente