はしがき:
PHP の実行時に必要なメモリは、複数回ではなく一度にオペレーティング システムに適用されます。では、どうやって一度に申請したのか、その仕組みは何だったのでしょうか?以下の紹介文をご覧ください。
ヒープ層は PHP メモリ管理のコア実装です 、PHP の最下位層のメモリ管理、ZendMM のシステムへのメモリ アプリケーションは、必要に応じてシステムに直接適用されるのではなく、 ZendMM 最下層 (ヒープ層) は、まずシステムから大きなメモリ ブロックを適用し、メモリ プールに似た管理メカニズムを確立します。設定解除後、ZendMM はメモリをすぐにシステムに直接返すのではなく、単にメモリをシステムに返すだけです。それを独自に維持し、メモリプール(ストレージ層)で利用可能なとして再識別します。
利点:
1.多くの事前定義された定数変数と何百ものメモリリクエストがあります。システムからのPHPの頻繁なメモリアプリケーション操作を回避し、OSへのリクエストの数を減らします。
2.実行速度は速くなりますが、プログラムの実行時間が長くなるとメモリ使用量が増加するため、5.3では新しいガベージコレクションメカニズムが導入されます。
詳細な分析は次のとおりです:
PHPのメモリ管理は階層的であるとみなすことができます。 ストレージ層(storage)、ヒープ層(heap)、インターフェース層(emalloc/efree)の3つの層に分かれています。 ストレージ層は実際には、malloc() や mmap() などの関数を通じてシステムからメモリを適用し、free() 関数を通じて要求されたメモリを解放します。
下の図に示すように、PHPメモリマネージャー。 PHP にはストレージ層に 4 つのメモリ割り当てスキームがあります: malloc、win32、mmap_anon、mmap_zero。デフォルトでは、malloc がメモリの割り当てに使用されます。通常、ストレージ層によって適用されるメモリブロックは比較的大きいですが、ここで適用される大規模なメモリは、ストレージ層構造によって必要とされるメモリを意味するのではなく、ストレージ層の構造によるヒープ層の割り当てを意味します。ストレージ層メソッドを呼び出すと、大きなチャンクのメモリに適用されます。ストレージ層の機能は、メモリ割り当てメソッドをヒープ層に対して透過的にすることです。
ZEND_WIN32 マクロが設定されている場合は、HeapAlloc が割り当てに呼び出されます。残りの 2 つのメモリ スキームは匿名メモリ マップであり、PHP のメモリ スキームは環境変数を設定することで変更できます。図 6.1 PHP メモリ マネージャー
PHP メモリ管理のコア実装です PHP の基礎となるメモリ管理は、小さいメモリ リスト (free_buckets)、大きいメモリ リスト (large_free_buckets)、および保持される残りのメモリ リスト (rest_buckets) の 3 つのリストに分割されます。層状に出ます。 ZendMM のシステムへのメモリ アプリケーションは、必要なときにすぐにシステムに適用されるのではなく、ZendMM の最下層 (ヒープ層) が最初にシステムに適用され、メモリの大きなブロックが埋められます。 メモリ プールと同様の管理メカニズムを確立します。
プログラムがメモリを使用する必要がある場合、ZendMMは使用するためにメモリプール内の対応するメモリを割り当てます。 これの利点は、次のコードのように、システムからの PHP の頻繁なメモリ アプリケーション操作を回避できることです:
<?php $tipi = "o_o\n"; echo $tipi; ?>ログイン後にコピーこれは単純な PHP プログラムですが、emalloc への呼び出しをカウントすると、変数を割り当てるだけの単なる PHP プログラムですが、PHP スクリプトの実行には多数の環境変数と定義が必要なので、これは非常に簡単に説明できます。内部変数 (詳細については、PHP コア -- ライフサイクルを参照)、 これらの定義自体をメモリに保存する必要があります。
PHP 拡張機能を作成する場合、malloc (オペレーティング システムのメモリ ブロックに適用) の代わりに、emalloc (zend_mm_storage 層のメモリ ブロックに適用) を使用することをお勧めします 、実際には、代わりに PHP の ZendMM を使用してください システムレベルのメモリ管理を手動で直接呼び出します。
ZendMM は、メモリ割り当てに _zend_mm_alloc_int 関数を使用します。プロセスは次のとおりです。
上記からも分かるように割り当て、PHP のメモリ 割り当ては、PHP の使用に基づいて設計されており、通常、単一スクリプトの実行サイクルは比較的短く (最大数秒)、アプリケーションでのメモリ ブロックをサポートします。割り当ての場合、隣接しないアドレスの複雑な空きメモリのマージは必要なく、システムに対する集中的な要求が再度行われます。 これの利点は、実行が高速になることです。欠点は、プログラムの実行時間が長くなることです。 メモリ使用量が「増加」します (PHP5.2 以前)。 したがって、PHP5.3 より前のバージョンは、デーモンプロセスとして長期的な動作には適していません。 (もちろん、他の解決方法もあり、PHP5.3 では新しい GC メカニズムが導入されています。詳細については、次のセクションを参照してください
PHP カーネル -- メモリ リークと新しいガベージ コレクション メカニズム)
2. 記憶の破壊
ZendMM は、メモリ破壊の処理においてメモリ アプリケーションと同じ戦略を採用しています。プログラムが変数の設定を解除したり、その他の解放動作を実行したりする場合、ZendMM はメモリをシステムに直接返さず、再実行するだけです。自身が維持するメモリプール(ストレージ層)で利用可能なとして識別し、 次のメモリ アプリケーションで使用するメモリのサイズに応じて、それらを上記の 3 つのリスト (小さい、大きい、空き) に整理します。
メモリ破壊の最終実装関数は_efreeです。 _efree では、メモリを破壊すると、まずメモリをキャッシュに戻すかどうかを決定する必要があります。 メモリ サイズが ZEND_MM_SMALL_SIZE を満たし、キャッシュがシステム設定 ZEND_MM_CACHE_SIZE を超えていない場合、現在のメモリ ブロック zend_mm_block は mm_heap->cache に戻されます。
メモリ破壊プロセスには、参照カウントとガベージ コレクション (GC) も含まれます。これについては、次のセクションで説明します。 PHP カーネル - メモリ リークと新しいガベージ コレクション メカニズムを参照してください
3. キャッシュ
は Wikipedia に次の説明があります: 速度が大幅に異なる場所2つのタイプの間2 つの間のデータ転送速度の違いを調整するために使用されるハードウェアをキャッシュと呼ぶことができます。 プロセッサとメモリ間の初期キャッシュから始まり、データ アクセスの速度を CPU の処理速度に適応させることがすべてです。 これは、メモリ内での「プログラムの実行とデータ アクセスのローカルな動作」の原則に基づいています。 同様に、PHP のメモリ管理におけるキャッシュも、「プログラムの実行とデータ アクセスのローカルな動作」の原則に基づいています。 キャッシュを導入する目的は、小さなメモリ ブロックに対するクエリの数を減らし (クエリを実行する前にキャッシュにヒットできるかどうかを確認する) 、最近アクセスしたデータへのアクセスを高速化することです。
PHP はメモリ管理メカニズムにキャッシュを追加し、次の処理を実行します:
· キャッシュとキャッシュのサイズ制限、つまりキャッシュをいつ使用するかを識別し、場合によっては最小限の設定でキャッシュを無効にできます。変更
・キャッシュの記憶構造、つまりキャッシュの記憶場所、構造、記憶ロジック
・キャッシュを初期化する
・キャッシュ内のコンテンツを取得する
・キャッシュに書き込む
キャッシュを解放する、またはキャッシュリストをクリアする
キャッシュ自体もストレージ層によって適用されるメモリに格納されます。メモリが足りない場合は、キャッシュを解放する必要があります。
ヒープメモリがオーバーフローすると、プログラムはzend_mm_free_cacheを呼び出してキャッシュを解放します。 解放プロセス全体は配列の走査であり、プログラムは配列要素ごとにリンク リスト内のその前の要素を走査し、メモリのマージ操作を実行して、ヒープ構造内のキャッシュ測定数を削減します。
以上がPHP カーネル -- メモリ管理とキャッシュ メカニズムの詳細な図による説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。