awk wyciek pamięci?

11

Na tej podstawie uruchamiam polecenie

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

Zauważam, że pamięć używana przez awk stale się powiększa podczas działania tego polecenia, na przykład zużywa ponad 500 MB pamięci do momentu odtworzenia 75 MB nieprzetworzonych danych audio. Wszystkie pozostałe polecenia w potoku utrzymują stałą ilość pamięci.

Do czego służy awk wykorzystujący tę pamięć i czy istnieje alternatywa, która przetwarza zamierzony strumień wykorzystując tylko stałą ilość pamięci?


na wypadek gdyby wersja awk miała znaczenie:

 awk --version
awk version 20070501

Oto polecenie, które przetestowałem na podstawie odpowiedzi Thomasa Dickeya:

< /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
źródło
Widzę także wyciek pamięci w moim systemie BSD-Darwin (Mac).
Otheus
Powiedziałeś, Here's the command I tested...ale zapomniałeś powiedzieć nam o wynikach tych testów - czy to rozwiązało problem, czy nie? Może nie dlatego, że każde odniesienie do elementu w a[]pętli tworzyłoby wpisy, gdyby nie istniały, więc jeśli nie istnieje - czy to pomaga, jeśli jawnie usuwasz tablicę przed podziałem lub po użyciu, np. 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)) }'? W tym segmencie kodu musisz pozostawić split () w jego oryginalnej lokalizacji, a nie przenosić go do BEGIN.
Ed Morton,

Odpowiedzi:

11

To stwierdzenie jest dziwne:

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

Powtarzalnie dzieli stały ciąg znaków, aby utworzyć tablicę a. Jeśli przeniesiesz to do BEGINsekcji, program powinien działać tak samo - bez przydzielania nowej kopii atablicy dla każdego rekordu wejściowego.

Adresowanie komentarzy: pętla for i wyrażenie nie przydzielają pamięci w prosty sposób. Szybkie porównanie mawk, gawk i awk pokazuje, że nie ma problemu z pierwszymi dwoma, ale /usr/bin/awkw OSX przecieka szybko. Jeśli Apple miałby system zgłaszania błędów, byłoby to dobre miejsce.

Thomas Dickey
źródło
1
Zrobiłem tak, jak zasugerowałeś na moim Macu (nie jestem OP). Nadal widzę wyciek pamięci z awk.
Otheus
Jakoś po prostu odwołanie się a pamięć niej korzysta hash.
Otheus
To samo tutaj; Nadal widzę wzrost pamięci. Zrobiłem też przybliżone porównanie i wydaje się, że użycie pamięci rośnie w tym samym tempie z tą zmianą.
bames53
Nawet to spowoduje wyciek pamięci:awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,","); } { for (i = 0; i < 1; i+= 0.0001) a[1]; }'
Otheus
Możesz przejść na mawk lub gawk. System podstawowy Apple zawiera kilka prawdziwych antyków.
Thomas Dickey,
5

Oto odpowiednik perla, który nie wycieka:

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

Jest prawie identyczny. $1zostaje zastąpiony przez $F[0]i ijest zastąpiony przez $i. Hash aotrzymuje o rzeczywistej tablicy @a.

Mądrze byłoby wygenerować jakieś dane wejściowe i porównać różnice wyjściowe i różnice między nimi. Często występują niuanse, w jaki sposób języki interpretacyjne radzą sobie z liczbą zmiennoprzecinkową.

Otheus
źródło