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が使用するメモリは継続的に増加します。たとえば、生のオーディオデータ75MBが再生されるまでに500MBを超えるメモリを消費します。パイプライン内の他のすべてのコマンドは、一定量のメモリを維持します。

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

BSD-Darwin(Mac)システムでもメモリリークが発生します。
Otheus 2016年

あなたは言った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を簡単に比較すると、最初の2つには問題がないことを示していますが/usr/bin/awk、OSXでは急速にリークします。もしAppleがバグ報告システムを持っていたら、それは行くべき場所でしょう。


1
私はMacであなたが提案したとおりにやった(私はOPではない)それでもawkでメモリリークが発生します。
Otheus 2016年

どういうわけか、単にハッシュを参照するとメモリを使用します。
Otheus 2016年

こっちも一緒; まだメモリの増加が見られます。大まかな比較も行いましたが、メモリの使用量はこの変更と同じ割合で増加しているようです。
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の基本システムには、いくつかの本物の骨董品が含まれています。
Thomas Dickey

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ます。

入力を生成して出力を比較し、2つの間の違いに注意することをお勧めします。解釈言語が浮動小数点をどのように処理するかについては、しばしば微妙な違いがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.