7

これは、大量のデータを複雑な方法で処理し、実行に数時間かかる PHP 5.3 Cli アプリケーションに関連しています。誰かが、ガベージ コレクションをオフにすると実行速度が大幅に向上することを発見しました (おそらく 50% 程度)。

このパフォーマンス ヒットについて言及している唯一の記事はhttp://derickrethans.nl/collecting-garbage-performance-considerations.htmlです。完全にフォローしているかどうかはわかりませんが、循環参照が多いコードにのみ適用されることを示唆しているようです。

誰かがこれに光を当てることができますか?

また、gc をオフにした場合、手動でメモリを削減する方法はありますか? unset() の使用が提案されています。簡単なテストでは、オブジェクトのサイズに関係なく、unset() によって約 80 バイトが解放されることが示されました。これは、参照の設定を解除しているだけであることを示唆しています。これは、私がオンラインで読んだことによって裏付けられています。変数がスコープから外れると、ガベージ コレクションがなくても、これらの 80 バイトがとにかく解放されると考えるのは正しいでしょうか?

4

2 に答える 2

4

循環参照 GC を無効にしました。通常のものはまだ動作します。

zval一般的な GC テストでは、変数やプロパティによって参照されなくなった s (「メモリ」)があるかどうかに関係なく、このメモリを解放します。循環参照とは、2 つ以上のオブジェクトが相互に直接的または間接的に参照する場合です。

$a = new stdClass;
$b = new stdClass;
$a->b = $b;
$b->a = $a;
unset($a, $b);

現在、両方のオブジェクトが相互に参照していますが、どちらも他の場所からは参照されていないため、到達できません。これは、循環参照 GC が検出しようとするものですが、それらを見つけるために、すべての既知のオブジェクトを反復処理し、「外部からの」参照があるかどうかを調べます。もう少し複雑ですが、単純化しました;) したがって、多くの参照、特に循環参照を持つ構造では、これは大きなタスクです。

言及する価値があります:unset()参照を削除するだけで、メモリを(直接)解放しないでください。これは後でGCによって行われます(そして、それは良い仕事をします:))

于 2013-01-24T12:33:45.483 に答える
2

を使用して、コードからサイクルを手動で削除できますunset。関数を実装することにより、クラスからサイクルをクリーンアップし__destructます。unset他のオブジェクトを参照するすべてのプライベート変数、保護変数、またはパブリック変数。

これを既存のプログラムに適用する場合は非常に面倒になりますが、実行可能です。


class A {
    public $ref;
    public function __destruct() {
        unset($this->ref);
        echo "destruct";
    }
}
$a1 = new A();
$a2 = new A();
$a1->ref = $a2;
$a2->ref = $a1;

これは機能しませ

unset($a1, $a2);
echo "--";
// prints --destructdestruct (in 5.3)

これは機能します:

$a1->__destruct();
unset($a1, $a2);
echo "--";
// prints destructdestructdestruct-- (in 5.3)
于 2013-01-24T12:39:28.140 に答える