PHP回収メカニズムの性能面で考慮した要因
4737 ワード
ここでは主に2つの分野が性能に影響を及ぼしている.1つ目はメモリ占有スペースの節約であり、もう1つはゴミ回収メカニズムがメモリクリーンアップを実行する際の実行時間の増加である(run-time delay).私たちはこの2つの分野を研究します.
メモリ容量の節約
まず、ごみ回収メカニズムを実現する全体的な理由は、前提条件が満たされると、循環参照の変数をクリーンアップすることでメモリ消費量を節約するためである.PHP実行中、ルートバッファがいっぱいになったりgc_を呼び出したりするとcollect_cycles()関数の場合、ゴミ回収が実行されます.下図では、以下のスクリプトがそれぞれPHP 5.2とPHP 5.3環境でのメモリ使用量を示し、スクリプト起動時にPHP自体が使用する基本メモリを排除しています.
Example #1 Memory usage example
この理論的な例では、オブジェクト自体を指すように設定されたオブジェクトを作成します.ループの次の反復(iteration)では、スクリプト内の変数が再コピーされると、典型的なメモリリークが発生します.この例では、2つの変数コンテナは漏れています(オブジェクトコンテナとプロパティコンテナ)が、可能なルートは1つしか見つかりません:unsetされた変数です.10000回の繰り返し(合計10000個の可能なルートが生成される)後、ルートバッファが満たされると、ゴミ回収メカニズムが実行され、関連する可能なルートのメモリが解放される.これはPHP 5.3の鋸歯型メモリ占有図から簡単に見ることができます.10000回の繰り返しが実行されるたびに、ゴミ回収が実行され、関連する繰り返し使用される参照変数が解放されます.この例では,漏洩したデータ構造が非常に簡単であるため,ごみ回収メカニズム自体があまり作業する必要はない.このグラフから、PHP 5.3の最大メモリ消費量は約9 Mbで、PHP 5.2のメモリ消費量は増加していることがわかります.
実行時間増加(Run-Time Slowdowns)
ごみ回収がパフォーマンスに影響する第2の分野は、漏洩したメモリを解放するのにかかる時間です.この時間の消費量を確認するために、上記のスクリプトを少し変更し、サイクル内のメモリ占有計算を繰り返し削除しました.2番目のスクリプトコードは次のとおりです.
Example #2 GC performance influences
このスクリプトを2回実行し、zendを構成します.enable_gcがごみ回収メカニズムを開くと、もう1つは閉じるときです.
Example #3 Running the above script
私のマシンでは、最初のコマンドの実行時間は約10.7秒で、2番目のコマンドは11.4秒かかります.時間的に7%増加した.しかし、このスクリプトを実行するとメモリ消費量のピークは98%減少し、931 Mbから10 Mbに減少した.この基準は科学的ではないか、実際のアプリケーションのデータを表すことはできませんが、ゴミ回収メカニズムのメモリ使用のメリットを示しています.幸いなことに、このスクリプトでは、実行中により多くのループ参照変数が発生した場合、メモリがより節約された場合、時間が増加するたびに7%増加します.
PHP内部GC統計
PHP内部では、ゴミ回収メカニズムがどのように動作しているかに関する情報をより多く表示できます.しかし、これらの情報を表示するには、benchmarkとdata-collecting codeを使用できるようにPHPを再コンパイルする必要があります.あなたの意思に従って実行する必要があります./configure前に、環境変数CFLAGSを-DGC_に設定BENCH=1.次のコマンド列はこのことをします.
Example #4 Recompiling PHP to enable GC benchmarking
新しくコンパイルしたPHPバイナリファイルで上記の例コードを再実行すると、PHP実行が終了すると、次の情報が表示されます.
Example #5 GC statistics
主な情報統計は最初のブロックにあります.ごみ回収メカニズムが110回実行され、この110回の実行では、合計2百万以上のメモリ割り当てが解放されていることがわかります.ゴミ回収機構が少なくとも1回作動限り、ルートバッファピークは常に10000である.
結論
通常,PHPにおけるゴミ回収メカニズムは,循環回収アルゴリズムが確実に実行されている場合にのみ時間消費が増加する.しかし、通常の(より小さい)スクリプトでは、パフォーマンスに影響はありません.
しかし、通常のスクリプトでリサイクルメカニズムが実行されている場合、メモリの節約により、このスクリプトをサーバ上で同時に実行することができます.合計メモリが上限に達していないためです.
この利点は、長時間のテストキットやdaemonスクリプトなど、長時間の実行スクリプトで特に顕著である.また、通常はWebスクリプトよりも長い時間実行されている»PHP-GTKアプリケーションに対して、新しいゴミ回収メカニズムは、メモリ漏洩の問題が解決しにくいと考えられていた見方を大幅に変えるはずです.
メモリ容量の節約
まず、ごみ回収メカニズムを実現する全体的な理由は、前提条件が満たされると、循環参照の変数をクリーンアップすることでメモリ消費量を節約するためである.PHP実行中、ルートバッファがいっぱいになったりgc_を呼び出したりするとcollect_cycles()関数の場合、ゴミ回収が実行されます.下図では、以下のスクリプトがそれぞれPHP 5.2とPHP 5.3環境でのメモリ使用量を示し、スクリプト起動時にPHP自体が使用する基本メモリを排除しています.
Example #1 Memory usage example
<?php
class Foo
{
public $var = '3.1415962654';
}
$baseMemory = memory_get_usage();
for ( $i = 0; $i <= 100000; $i++ )
{
$a = new Foo;
$a->self = $a;
if ( $i % 500 === 0 )
{
echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "
";
}
}
?>
この理論的な例では、オブジェクト自体を指すように設定されたオブジェクトを作成します.ループの次の反復(iteration)では、スクリプト内の変数が再コピーされると、典型的なメモリリークが発生します.この例では、2つの変数コンテナは漏れています(オブジェクトコンテナとプロパティコンテナ)が、可能なルートは1つしか見つかりません:unsetされた変数です.10000回の繰り返し(合計10000個の可能なルートが生成される)後、ルートバッファが満たされると、ゴミ回収メカニズムが実行され、関連する可能なルートのメモリが解放される.これはPHP 5.3の鋸歯型メモリ占有図から簡単に見ることができます.10000回の繰り返しが実行されるたびに、ゴミ回収が実行され、関連する繰り返し使用される参照変数が解放されます.この例では,漏洩したデータ構造が非常に簡単であるため,ごみ回収メカニズム自体があまり作業する必要はない.このグラフから、PHP 5.3の最大メモリ消費量は約9 Mbで、PHP 5.2のメモリ消費量は増加していることがわかります.
実行時間増加(Run-Time Slowdowns)
ごみ回収がパフォーマンスに影響する第2の分野は、漏洩したメモリを解放するのにかかる時間です.この時間の消費量を確認するために、上記のスクリプトを少し変更し、サイクル内のメモリ占有計算を繰り返し削除しました.2番目のスクリプトコードは次のとおりです.
Example #2 GC performance influences
<?php
class Foo
{
public $var = '3.1415962654';
}
for ( $i = 0; $i <= 1000000; $i++ )
{
$a = new Foo;
$a->self = $a;
}
echo memory_get_peak_usage(), "
";
?>
このスクリプトを2回実行し、zendを構成します.enable_gcがごみ回収メカニズムを開くと、もう1つは閉じるときです.
Example #3 Running the above script
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%増加した.しかし、このスクリプトを実行するとメモリ消費量のピークは98%減少し、931 Mbから10 Mbに減少した.この基準は科学的ではないか、実際のアプリケーションのデータを表すことはできませんが、ゴミ回収メカニズムのメモリ使用のメリットを示しています.幸いなことに、このスクリプトでは、実行中により多くのループ参照変数が発生した場合、メモリがより節約された場合、時間が増加するたびに7%増加します.
PHP内部GC統計
PHP内部では、ゴミ回収メカニズムがどのように動作しているかに関する情報をより多く表示できます.しかし、これらの情報を表示するには、benchmarkとdata-collecting codeを使用できるようにPHPを再コンパイルする必要があります.あなたの意思に従って実行する必要があります./configure前に、環境変数CFLAGSを-DGC_に設定BENCH=1.次のコマンド列はこのことをします.
Example #4 Recompiling PHP to enable GC benchmarking
export CFLAGS=-DGC_BENCH=1
./config.nice
make clean
make
新しくコンパイルしたPHPバイナリファイルで上記の例コードを再実行すると、PHP実行が終了すると、次の情報が表示されます.
Example #5 GC statistics
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回の実行では、合計2百万以上のメモリ割り当てが解放されていることがわかります.ゴミ回収機構が少なくとも1回作動限り、ルートバッファピークは常に10000である.
結論
通常,PHPにおけるゴミ回収メカニズムは,循環回収アルゴリズムが確実に実行されている場合にのみ時間消費が増加する.しかし、通常の(より小さい)スクリプトでは、パフォーマンスに影響はありません.
しかし、通常のスクリプトでリサイクルメカニズムが実行されている場合、メモリの節約により、このスクリプトをサーバ上で同時に実行することができます.合計メモリが上限に達していないためです.
この利点は、長時間のテストキットやdaemonスクリプトなど、長時間の実行スクリプトで特に顕著である.また、通常はWebスクリプトよりも長い時間実行されている»PHP-GTKアプリケーションに対して、新しいゴミ回収メカニズムは、メモリ漏洩の問題が解決しにくいと考えられていた見方を大幅に変えるはずです.