ガベージ コレクター (GC) は PHP の内部メモリ管理システムですが、理解すべき微妙な点がいくつかあります。
GC はメモリ管理を自動化し、手動タスクでメモリを処理する煩わしさ (面倒な作業) を排除します。
これにより、開発者は「メモリ不足」エラーについて過度に心配することなく、ビジネス ロジックに集中できるようになります。
もちろん、それは魔法ではありません。
不要になったオブジェクトを解放すると、メモリ リークが防止されます。
GC はカウント メカニズムを使用して、削除する要素を決定します。特定のオブジェクトを指す参照がない場合 (つまり、$counter = 0)、このオブジェクトはクリーンアップの対象になります。
かなりうまく機能しますが、一部の参照には問題がある可能性があります:
class A { public $b; } class B { public $a; } $a = new A(); $b = new B(); $a->b = $b; $b->a = $a; unset($a); unset($b);
この設計が悪い場合、$a と $b の設定を解除しても、PHP はメモリを解放しません。$a と $b は相互参照しているため、PHP はそれらがまだ使用されていると認識します。
幸いなことに、そのための Cycle Collector と呼ばれる別のメカニズムがあります:
gc_collect_cycles();
大まかに言えば、コレクターはすべての参照を走査し、アルゴリズムを適用して使用中のオブジェクトにマークを付けます。これにより、収集するオブジェクト (マークされていないオブジェクト) が明らかになります。
ただし、循環参照の可能性がある 10,000 オブジェクトのしきい値に達するまで、PHP は自動循環収集をトリガーしません。
繰り返しますが、これは魔法ではないため、gc_collect_cycles() を呼び出す必要があるのはごく限られた場合のみです。
設計が悪いと、オブジェクト間の関係が複雑になり、参照が増え、ガベージ コレクションが頻繁に発生する可能性があります。
参照カウントされる各オブジェクトには、参照カウント用に追加のストレージが必要です。
出典: Wikipedia - 参照カウント
メモリ クリーンアップ操作に関連するオーバーヘッドは、全体的なパフォーマンスに大きな影響を与え、最終的には特定のシナリオでの実行時間を増加させる可能性があります。
10 年前、Composer は gc_disable() 関数を使用するだけでパフォーマンスが大幅に向上しました。
ソース: Composer - GC の無効化
確かに、PHP 7 では GC が大幅に改善されたため、2014 年とは異なります。
さらに、PHP 8 バージョンではメモリ割り当て戦略が改善され、監視を強化するために GC 操作に関する有用な統計が追加されました (8.3 の gc_status())。
ほとんどの PHP アプリケーションはリクエスト駆動型であり、メモリはリクエストの終了時に自動的にクリアされます。
繰り返しますが、これはとてもクールですが、魔法ではありません。非同期リクエストと存続期間の長いオブジェクト/デーモンでは何が起こりますか?
ある時点でメモリ リークが発生する可能性があります。
この時点では、PHP の GC が他の言語とどのように異なるのかがわからないかもしれません。
ほとんどの場合、他の言語はガベージを収集するために参照カウントに依存していないか、異なる実装を使用している可能性があります。
たとえば、多くの場合、未使用のオブジェクトにもマークを付けるトレース アルゴリズムが使用されますが、段階的には動作しません。それはグラフの走査です。
さらに、一部の言語ではそのような直接制御 (実行時のオン/オフなど) が許可されていません。
いつものように、いくつかの利点と不便があるため、いくつかのハイブリッドなアプローチが見られるかもしれません。
組み込みの gc_* ヘルパーを利用できます。
例えば:
これらの関数は、必要に応じてガベージ コレクションのデバッグや微調整に役立ちます。
さらに詳しい情報については、この投稿をお読みください:
PHP 7.4 では弱い参照が導入され、PHP 8 では弱いマップが導入されました。
弱いマップは、弱い参照のコレクションとして説明できます。
このデータ構造は、混乱を生じさせたり過剰なスペースを消費したりすることなく、PHP が項目を追跡するのに役立つ多用途のキーと値のストアです。
ガベージ コレクションを妨げる可能性のある [強力な] 参照がないため、不要になったらすぐに消去される一時ストレージとして見ることができます:
$object = new stdClass; $map = new WeakMap(); $map[$object] = true; $object->name = 'some name'; print_r($map);// $object is stored in $map unset($object); print_r($map);// $object is cleaned and no longer available
ほとんどの用途では、PHP がすでにメモリ管理を処理しているため、メモリ管理について心配する必要はありません。
ただし、最新のスタックでは有効期間の長いオブジェクトが使用されているため、アプリケーションでメモリ リークの可能性がないか監視する必要があります。
問題が発生した場合は、コードを最適化するか、GC を直接操作する必要がある場合があります。
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3