утечка памяти в awk?

11

Основываясь на этом, я управляю командой

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

Я заметил, что объем памяти, используемой awk, постоянно увеличивается во время выполнения этой команды, например, он потребляет более 500 МБ памяти к моменту воспроизведения 75 МБ необработанных аудиоданных. Все остальные команды в конвейере поддерживают постоянный объем памяти.

Для чего awk использует эту память, и есть ли альтернатива, которая предназначена для обработки потока, используя только постоянный объем памяти?


если версия awk имеет значение:

 awk --version
awk version 20070501

Вот команда, которую я протестировал на основе ответа Томаса Дики:

< /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
источник
Я также вижу утечку памяти в моей системе BSD-Darwin (Mac).
Отеус
Вы сказали, Here's the command I tested...но забыли сообщить нам результат этого тестирования - это решило проблему или нет? Это может не произойти, поскольку каждая ссылка на элемент в a[]цикле создаст записи, если они не существуют, а если нет, то поможет ли это, если вы явно удалите массив перед его разбиением или после его использования, например 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)) }'? С этим сегментом кода вам нужно оставить split () в исходном месте, а не перемещать его в BEGIN.
Эд Мортон

Ответы:

11

Это утверждение странно:

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

Повторно разбивает постоянную строку для создания массива a. Если вы перемещаете это в BEGINраздел, программа должна работать так же - без выделения новой копии aмассива для каждой входной записи.

Адресация комментариев: цикл for и выражение не выделяют память простым способом. Быстрое сравнение mawk, gawk и awk показывает, что с первыми двумя проблем нет, но /usr/bin/awkв OSX происходит утечка быстро. Если бы у Apple была система сообщений об ошибках, это было бы подходящим вариантом.

Томас Дики
источник
1
Я сделал, как вы предложили на моем Mac (я не OP). Я все еще вижу утечку памяти с помощью awk.
Отеус
Так или иначе, просто ссылки на а память хэш использует.
Отей
Тоже самое; Я все еще вижу рост памяти. Я также сделал грубое сравнение, и с этим изменением, похоже, увеличивается использование памяти.
bames53
Даже это приведет к утечке памяти:awk 'BEGIN { split("0,2,4,5,7,9,11,12",a,","); } { for (i = 0; i < 1; i+= 0.0001) a[1]; }'
Otheus
Вы можете переключиться на mawk или gawk. Базовая система Apple включает в себя настоящий антиквариат.
Томас Дики
5

Вот эквивалент Perl, который не пропускает:

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

Это почти идентично. $1заменяется на $F[0]и iзаменяется на $i. Хеш aзаменяется фактическим массивом @a.

Было бы целесообразно сгенерировать некоторые входные данные и сравнить выходные данные и отметить различия между ними. Часто возникают нюансы того, как интерпретирующие языки работают с плавающей запятой.

Otheus
источник