7

AWS DynamoPHPAPIを使用するPHPで記述されたスクリプトがあります。ダイナモから大量のデータを取得して処理する長いループを実行します。

'top'を使用してプロセスを見ると、'php'プロセスで使用されているメモリ使用量を確認できます。

スクリプトのループ内で、memory_get_usage(true)の結果を出力します

私がテストを実行するとき、これらの2つの値はリモートでさえ類似していません...

彼らはそうあるべきですか?そうでない場合はどうしてですか?

私のテストでは、1.7 GBのRAMを搭載したサーバーがあり、php.iniのmemory_limitを64Mに設定しました。また、スクリプトの開始時にgc_enable()を呼び出し、各ループの間にガベージコレクションを強制することを期待してgc_collect_cycles()を呼び出します。

'top'を使用してphpスクリプトを見ると、%MEMが上昇しているのがわかります。最終的には、95%を超え、Linuxがphpプロセスを強制終了します。これは'dmesg'を見るとわかります。ループの各反復からのプリントアウトを見ると、memory_get_usage(true)によって報告されたメモリ使用量が50MBを超えることはありません。

Linuxはスクリプトがほぼ1.7GBを使用していると考えていますが、phpは50MBしか使用していないと考えています。

どうしたの?

スクリプトにメモリリークがある場合でも、memory_get_usage(true)がメモリを考慮しない理由がわかりません...

アップデート

ループ内で実行している処理のさまざまな部分をコメントアウトするのに時間を費やした後、次のコードを削除すると、次のことがわかりました。

class cMyClass {
    public static function static_cmp_fn(&$a, &$b) {
        if ($a['att'] == $b['att']) { return 0; }
        $ret = ($a['att'] < $b['att']) ? -1 : +1;
        return $ret;
    }
    function DoProcessing(){
        $sort_fn = array("cMyClass", "static_cmp_fn");
        usort($this->m_dictToSort, $sort_fn); 
        unset($sort_fn);
    }

}

phpがシステムメモリをすべて消費することはありません。usortがメモリリークを起こしているように見えますが、理由はわかりません。私が理解していないのは、PHPが使用しているメモリの量について間違った情報を報告する理由です...

何か案は?

4

1 に答える 1

1

ループ内で実行している処理のさまざまな部分をコメントアウトするのに時間を費やした後、次のコードを削除すると次のことがわかりました。

$sort_fn = array("cMyClass", "static_cmp_fn");
usort($this->m_dictToSort, $sort_fn); 

php がすべてのシステム メモリを消費することはありません。usort がメモリをリークしているように思えますが、その理由はわかりません。

どうやらそうです。マニュアルを参照してください:

http://php.net/manual/en/function.usort.php

「ここのいくつかの例では、ソートに 'create_function' の使用を推奨していますが、これは usort の制限のために使用したくなるものです。しかし、この方法には注意してください --作成された関数は、ソート ルーチンの最後で解放されません。メモリ リークです。このため、このメソッドは使用しないでください。」

メソッドは似たarray()ようなことをしているようです。おそらく、メソッドを外部から呼び出すラッパー関数を宣言できますか?

アップデート

何が起こるかを見るために小さなテストケースを構築しようとしました。まだリークを再現できません。おそらく、何static_cmp_fn()が機能し、どのようm_dictToSortに構造化されているかについてのより多くのデータがあります。単純な比較では、奇妙なことは何もトリガーされません。ループ内で文字列、配列、またはオブジェクトを割り当てることもありません。ガベージ コレクターはそれらを強制終了し、メモリは少なくなります。

私が思ったように、まったくソートしない、または非常に基本的なソートを行う別のusort関数を呼び出して、問題がその呼び出し可能オブジェクトで何かおかしいことをしているのかどうかを確認することで、問題をさらに制限します(そうではないようです、そして私が間違っていた)、または比較関数内で何かおかしなことが起こっている場合。

于 2012-09-28T13:40:55.993 に答える