ホームページ  >  記事  >  バックエンド開発  >  PHP ガベージ コレクション メカニズム - パフォーマンスに関する考慮事項

PHP ガベージ コレクション メカニズム - パフォーマンスに関する考慮事項

伊谢尔伦
伊谢尔伦オリジナル
2016-11-22 09:57:491190ブラウズ

リサイクルはパフォーマンスにわずかな影響を与える可能性がありますが、これは PHP 5.2 と PHP 5.3 を比較した場合にのみ発生します。 PHP 5.2 ではログをまったく記録しない場合よりも遅くなる可能性がありますが、PHP 5.3 では PHP ランタイムに加えられたその他の変更により、このパフォーマンスの低下が軽減されます。

パフォーマンスに影響を与える主な領域は 2 つあります。 1 つはメモリ領域の節約であり、もう 1 つはガベージ コレクション メカニズムがメモリ クリーニングを実行する際の実行時間 (実行時遅延) の増加です。両方の領域を見ていきます。

メモリ フットプリントの節約

まず第一に、ガベージ コレクション メカニズムを実装する全体の理由は、前提条件が満たされた後に循環参照される変数をクリーンアップすることでメモリ フットプリントを節約することです。 PHP の実行では、ルート バッファがいっぱいになるか、gc_collect_cycles() 関数が呼び出されると、ガベージ コレクションが実行されます。以下の図は、PHP 5.2 および PHP 5.3 環境における次のスクリプトのメモリ使用量を示しています。ただし、スクリプトの開始時に PHP 自体が占有する基本メモリは除きます。

例 #1 メモリ使用例

<?php
    class Foo
    {
        public $var = &#39;3.1415962654&#39;;
    }
    $baseMemory = memory_get_usage();
    for ( $i = 0; $i <= 100000; $i++ )
    {
        $a = new Foo;
        $a->self = $a;
        if ( $i % 500 === 0 )
        {
            echo sprintf( &#39;%8d: &#39;, $i ), memory_get_usage() - $baseMemory, "\n";
        }
    }
?>

PHP ガベージ コレクション メカニズム - パフォーマンスに関する考慮事項

この非常に理論的な例では、オブジェクトを作成し、このオブジェクトのプロパティがオブジェクト自体を指すように設定されます。一般的なメモリ リークは、ループの次の反復中にスクリプト内の変数が再度コピーされるときに発生します。この例では、2 つの変数コンテナー (オブジェクト コンテナーと属性コンテナー) がリークされていますが、ルート候補は 1 つだけ見つかります: 設定解除された変数です。 10,000 回繰り返した後 (結果としてルートの可能性は合計 10,000 個になります)、ルート バッファーがいっぱいになると、ガベージ コレクション メカニズムが実行され、ルートの可能性があるメモリが解放されます。これは、PHP 5.3 のノコギリ状のメモリ使用量グラフで簡単にわかります。 10,000 回の繰り返しが実行されるたびに、ガベージ コレクションが実行され、関連する再利用された参照変数が解放されます。この例では、リークされたデータ構造が非常に単純であるため、ガベージ コレクション メカニズム自体はそれほど多くの作業を行う必要はありません。このグラフから、PHP 5.3 の最大メモリ フットプリントは約 9 Mb であるのに対し、PHP 5.2 のメモリ フットプリントは増加し続けていることがわかります。

実行時の速度低下

ガベージ コレクションがパフォーマンスに影響を与える 2 番目の領域は、リークしたメモリを解放するのにかかる時間です。これにどれくらいの時間がかかるかを確認するために、上記のスクリプトを少し変更して、繰り返しを増やし、ループ内のメモリ使用量の計算を削除しました。

例 #2 GC パフォーマンスへの影響

<?php
    class Foo
    {
        public $var = &#39;3.1415962654&#39;;
    }
    for ( $i = 0; $i <= 1000000; $i++ )
    {
        $a = new Foo;
        $a->self = $a;
    }
    echo memory_get_peak_usage(), "\n";
?>

これを実行します。スクリプトは 2 回実行されます。1 回目は zend.enable_gc を構成してガベージ コレクションがオンになったとき、もう 1 回はオフになったときです。

例 #3 上記のスクリプトの実行

time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php
# and
time php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php

私のマシンでは、最初のコマンドは約 10.7 秒かかり、2 番目のコマンドは 11.4 秒かかりました。時間が7%増加しました。ただし、このスクリプトを実行するときのピーク メモリ使用量は、931Mb から 10Mb に 98% 削減されました。このベンチマークはあまり科学的ではなく、実際のアプリケーション データを代表するものでもありませんが、メモリ フットプリントの観点からガベージ コレクションの利点を示しています。良いニュースとしては、このスクリプトでは、実行中に循環参照変数がより多く出現すると、メモリの節約がさらに大きくなり、毎回の時間の増加率が 7% になるということです。

PHP 内部 GC 統計

PHP 内部で、ガベージ コレクション メカニズムがどのように動作するかに関する詳細情報を表示できます。ただし、この情報を表示するには、まず PHP を再コンパイルして、ベンチマークとデータ収集コードを使用できるようにする必要があります。必要に応じて ./configure を実行する前に、環境変数 CFLAGS を -DGC_BENCH=1 に設定する必要があります。次のコマンド文字列はまさにそれを行います:

例 #4 GC ベンチマークを有効にするために PHP を再コンパイルする

export CFLAGS=-DGC_BENCH=1
./config.nice
make clean
make

新しくコンパイルされた PHP バイナリ ファイルを使用して上記のサンプル コードを再実行すると、PHP の実行が終了した後、次の内容が表示されます。情報:

例 #5 GC 統計

GC Statistics
-------------
Runs:               110
Collected:          2072204
Root buffer length: 0
Root buffer peak:   10000
      Possible            Remove from  Marked
        Root    Buffered     buffer     grey
      --------  --------  -----------  ------
ZVAL   7175487   1491291    1241690   3611871
ZOBJ  28506264   1527980     677581   1025731

主な情報統計は最初のブロックにあります。ガベージ コレクション メカニズムが 110 回実行され、この 110 回の実行で合計 200 万を超えるメモリ割り当てが解放されたことがわかります。ガベージ コレクション メカニズムが少なくとも 1 回実行される限り、ルート バッファー ピーク (ルート バッファー ピーク) は常に 10000 です。

結論

通常、PHP のガベージ コレクション メカニズムは、ループ コレクション アルゴリズムが実際に実行されているときにのみ時間を消費します。増加。ただし、通常の (小規模な) スクリプトでは、パフォーマンスへの影響はまったくありません。

ただし、リサイクルメカニズムが実行されている通常のスクリプトの場合、メモリの節約により、より多くのそのようなスクリプトをサーバー上で同時に実行できるようになります。使用メモリの合計が上限に達していないためです。

この利点は、長時間実行されるテスト スイートやデーモン スクリプトなど、長時間実行されるスクリプトで特に顕著です。同時に、一般的に Web スクリプトよりも実行時間が長い PHP-GTK アプリケーションの場合、新しいガベージ コレクション メカニズムによって、メモリ リークの解決が難しいという長年の見方が大きく変わるはずです。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。