vazamento de memória awk?

11

Base em this Estou executando o 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

Noto que a memória usada pelo awk cresce continuamente enquanto este comando está em execução, por exemplo, consumindo mais de 500MB de memória no momento em que 75MB de dados de áudio brutos foram reproduzidos. Todos os outros comandos no pipeline mantêm uma quantidade constante de memória.

O que é awk usando essa memória e existe uma alternativa que faz o processamento de fluxo desejado usando apenas uma quantidade constante de memória?

caso a versão do awk seja importante:

⑆ awk --version
awk version 20070501

Aqui está o comando que testei com base na resposta 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
    
por bames53 05.03.2016 / 23:12

2 respostas

11

Esta afirmação é estranha:

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

Ele divide repetidamente uma string constante para criar uma matriz a . Se você mover isso para uma seção BEGIN , o programa deve funcionar da mesma forma - sem alocar uma nova cópia da matriz a para cada registro de entrada.

Endereçamento de comentários: o for-loop e a expressão não alocam memória de maneira simples. Uma comparação rápida de mawk, gawk e awk mostra que não há nenhum problema com os dois primeiros, mas /usr/bin/awk no OSX vaza rapidamente. Se a Apple tivesse um sistema de relatório de bugs, esse seria o lugar certo.

    
por 05.03.2016 / 23:23
5

Veja um equivalente em perl que não vaza:

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

É quase idêntico. $1 é substituído por $F[0] e i é substituído por $i . O hash a é substituído por um array real, @a .

Você seria sábio para gerar alguma entrada e comparar a saída e observar as diferenças entre os dois. Muitas vezes há nuances sobre como linguagens interpretativas lidam com ponto flutuante.

    
por 05.03.2016 / 23:50

Tags