5

こんにちは、Perl 変数で大きな文字列データを扱っています (生のメール本文なので、添付ファイルを含めることができます)。Perl のsubstrに興味深い問題があります。そのリークまたは何か間違ったことをしているようです (はいの場合、何ですか?)。コードを検討してください:

#!/usr/local/bin/perl
use strict;
my $str = 'a'x10_000_000;

system("ps up $$"); #22mb used (why?)
#USER   PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
#alt  64398  0,0  0,2 33292 22700   7  S+J  22:41     0:00,03 /usr/local/bin/perl ./t.pl

substr($str, 0, 1)='';
system("ps up $$"); #No leak
#USER   PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
#alt  64398  0,0  0,2 33292 22732   7  S+J  22:41     0:00,04 /usr/local/bin/perl ./t.pl

substr($str, 500);
system("ps up $$"); #Leaked 10Mb (why?!)
#USER   PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
#alt  64398  0,0  0,3 43532 32520   7  S+J  22:41     0:00,05 /usr/local/bin/perl ./t.pl

my $a = substr($str, 500);
system("ps up $$"); #Leaked 10Mb + Copyed 10Mb
#USER   PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
#alt  64398  0,0  0,5 64012 52096   7  S+J  22:41     0:00,09 /usr/local/bin/perl ./t.pl

undef $a; #Free scalar's memory
system("ps up $$"); #Free'd 10Mb
#USER   PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
#alt  64398  0,0  0,4 53772 42308   7  S+J  22:41     0:00,09 /usr/local/bin/perl ./t.pl

# Total leaked 2 times for 10Mb each

コマンドを見てくださいsubstr($str, 500);。さらに、文字列の戻りコピー(それで問題ありません)、同じ量のメモリがリークするため、戻り値を2回使用すると、スクリプトが動作している間、そのうちの1つが失われます...また、そうではないようです呼び出しがリークするため、一種の「内部バッファー」 ..

この 10Mb の増加のケースは、後続の呼び出しがますます多くのメモリを取得するため、「再利用可能な」メモリではないことに注意してください。

それを修正または回避する方法について何か提案はありますか?

私の Perl バージョン 5.14.2; 仕事で得たのと同じ動作(5.8.8)

4

2 に答える 2

2

ps割り当てる前にチェックを入れる$strと、perl を実行するためだけに約 2 MB が使用されていることがわかります。したがって、割り当て$strには、作成される文字列のサイズの 2 倍の 20 MB が必要です。何が起こっているのかを推測する必要がある場合、perl は 10 メガの文字列を作成し、それを にコピーする必要があり$strます。20メガ。後で使用するために、割り当てられたメモリを保持します。

substr($str, 0, 1)=''$strDevel::Peek でこれを確認できますが、プロセス メモリは増加しません。のメモリ割り当てから解放されたメモリを使用した可能性があります'a' x 10_000_000

my $a = substr($str, 500);同様の問題があります。はsubstr、新しい 10 MB の文字列を作成し、$a必要な 20 MB にコピーします。これを行うためにシステムメモリが必要になる理由はわかりません。オペレーティング システムから取得した以前の 10 メガ チャンクから perl がメモリを割り当てた可能性があるため、単一の 10 メガ チャンクではなくなり、OS にさらに要求する必要がありました。

undef $aDevel $a::Peek で確認できますが、perl は必ずしもメモリをオペレーティング システムに解放するとは限りません。

とにかくそれが私の最善の推測です。

簡単に言うと、プロセスによってメモリが解放されてオペレーティング システムに戻るのは複雑であり、オペレーティング システムはそれを別の方法で行います。これは特にperlに関する 1 つの議論Linuxに関する 1 つの議論です。

于 2012-11-28T20:02:45.470 に答える