vazamento de memória awk?

11

Com base nisso , 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

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

Para que serve o awk usando essa memória e existe uma alternativa que processa o fluxo pretendido usando apenas uma quantidade constante de memória?


caso a versão 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
bames53
fonte
Também vejo um vazamento de memória no meu sistema BSD-Darwin (Mac).
Otheus
Você disse, Here's the command I tested...mas esqueceu de nos contar o resultado desse teste - isso resolveu o problema ou não? Pode não ser que todas as referências a um elemento no a[]loop criem entradas se elas não existirem, se não existirem - ajuda se você excluir explicitamente a matriz antes de dividir ou depois de usá-la, por exemplo 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)) }'? Com esse segmento de código, você precisa deixar o split () no local original, não movê-lo para BEGIN.
Ed Morton

Respostas:

11

Esta afirmação é estranha:

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

Ele divide repetidamente uma cadeia constante para criar uma matriz a. Se você mover isso para uma BEGINseção, o programa funcionará da mesma maneira - sem alocar uma nova cópia da amatriz para cada registro de entrada.

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

Thomas Dickey
fonte
1
Fiz o que você sugeriu no meu Mac (não sou o OP). Eu ainda vejo uma memória vazar com awk.
Otheus
De alguma forma, simplesmente fazendo referência a uma memória de hash usos.
Otheus
O mesmo aqui; Eu ainda vejo o crescimento da memória. Também fiz uma comparação aproximada e o uso da memória parece estar crescendo na mesma taxa com essa alteração.
bames53
Mesmo isso causará um vazamento de memória:awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,","); } { for (i = 0; i < 1; i+= 0.0001) a[1]; }'
Otheus 5/16
Você pode mudar para mawk ou gawk. O sistema básico da Apple inclui algumas antiguidades reais.
Thomas Dickey
5

Aqui está um equivalente 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 uma matriz real @a,.

Seria sensato gerar alguma entrada e comparar a saída e observar as diferenças entre as duas. Muitas vezes existem nuances de como as linguagens interpretativas lidam com o ponto flutuante.

Otheus
fonte