PHPでオブジェクトが消費するメモリの量と64ビットバージョンを使用する価値はありますか?



この投稿は、現在の大規模なZendFrameworkプロジェクトのメモリ消費量の調査から着想を得たものです。 いつものように、研究の結果によると、私たちがプログラムの慢さにショックを受けました。これは、PHPで何か大きなものを書くときによくあります。 そして、おそらく、PHPだけではありません。

しかし、まず最初に。

この記事は、次の記事の論理的な続きです。


どのように測定しますか


まず、「重量」の測定方法を決定します。 テンプレートは次のとおりです。
$startMemory = 0; $startMemory = memory_get_usage(); //  echo (memory_get_usage() - $startMemory) . ' bytes' . PHP_EOL; 

このようなテンプレートは、新しく割り当てられたメモリ、つまり変数のメモリを測定するのに適しています。 しかし、スクリプトが開始される前にメモリに保存されるため、このアプローチでどの程度の定義、つまり関数とクラスの記述が食べられるかを測定することは不可能です。 定義を測定するために、次のテンプレートを使用します。
 $startMemory = 0; $startMemory = memory_get_usage(); //  include $testfile; echo (memory_get_usage() - $startMemory - $include_overhead) . ' bytes' . PHP_EOL; 

$ include_overheadは、内部のニーズに合わせてincludeステートメントが消費する量です。 この記事では、$ include_overheadの測定方法については学習しません。 消費されるメモリのサイズは、次の3つのことに依存することに注意してください。

誰もがこの詳細を調査することに興味がある場合、ファイルrun.include-test.phpを調べることができます。これは、インクルード中のメモリ消費の不均一性を非常によく示しています。 また、以下のすべてのテストでは、正確な値は必要ないが、32ビットバージョンと64ビットバージョンの傾向と違いが必要なので、およそ$ include_overheadを測定します。

「オブジェクト」の重さ


そのため、TestSuiteは、多数のテストを自動的に実行するように作成されました。 すべてのテストは、 Ubuntu 12.04.1 LTS i386およびUbuntu 12.04.1 LTS amd64の VirtualBoxで実行されました。 PHPバージョン-5.3.10、ZendFramework-1.11.11。 コンソールで実行するコマンド:
 php run.testsuite-without-accelerator.php 
さらに、制御のためにGentoo amd64を使用してマシンでテストを行いました。 コンソールから起動した場合、PHPアクセラレータは機能しません。 結果は次のとおりです。
テスト名説明Ubuntu x86、
PHP 5.3.10、
ZF 1.11.11
Ubuntu x86-64、
PHP 5.3.10、
ZF 1.11.11
Gentoo x86-64、
PHP 5.3.15、
ZF 1.11.4
a.mention_variable可変言及448048
a.new_null_variable新しいヌル変数の作成108208144
a.unset_null_variable変数を削除-108-208-144
stdClass.newオブジェクト作成120232168
stdClass.tovar1オブジェクトを作成して$ aをリンクする264512352
stdClass.tovar2_unset_and_thesameリンク$ aを削除し、リンク$ aを再作成します000
stdClass.tovar3_unset_and_anotherリンク$ aを削除してリンク$ bを作成000
stdClass.tovar4_anotherオブジェクトを作成して$ cをリンクする264512352
stdClass.tovar5_addlink$ aを$ bと同じオブジェクトにリンクします6412896
stdClass.z.free_memory$ a、$ b、および$ cリンクの削除-592-1152-800
myclass.a.emptyクラスAの説明70013441128
myclass.aa.interfaceインターフェイスの説明A70013441128
myclass.ab.final最終クラスABの説明70013441128
myclass.ac.abstractAC抽象クラスの説明70013441128
myclass.b.extended.emptyAを拡張するクラスBの説明70013441128
myclass.c.empty.namespace空の名前空間Cの説明000
myclass.d.constructクラスDコンストラクターの説明110422881920
myclass.dd.methodメソッドを使用したDDクラスの説明108822801912
myclass.ddd.private.varプライベート変数を持つDDDクラスの説明96018401472
myclass.dddd.public.varパブリック変数を持つDDDDクラスの説明96018401472
myclass.ddddd.static.var静的変数を持つDDDDDクラスの説明96018401472
myclass.e.extended.destructクラスDを拡張するデストラクタを使用したクラスEの説明134427042272
myclass.e.instance.abABオブジェクトと$ eリンクの作成264512352
myclass.e.instance.dddddDDDDDオブジェクトと$ eリンクの作成000
myclass.e.instance.eオブジェクトEを作成し、$ eにリンクします000
myclass.f.instance.dddddDDDDDオブジェクトと$ fリンクの作成264512352
myclass.z.free_memoryリンクの削除$ e、$ f-484-944-656
zend.a.init.autoloadZendFrameworkの自動ロードを初期化する127 444276,288249 232
zend.a.init.modelベースのデフォルトアダプターの初期化1 018 3882 081 6001 871 256
zend.extended.controller1Zend_Controller_Actionからのコントローラー定義。 途中で、標準のZendクラスをロードします378,296809 384712 816
zend.extended.controller2コントローラーの定義。 Zendクラスは既にロードされています。クラスの重量を確認してください11 32819 60816,008
zend.extended.model1Zend_Db_Tableによるモデル定義。 途中で、標準Zendクラスのロードが行われます。27 93648 54440 224
zend.extended.model2モデルの定義。 Zendクラスは既にロードされています。クラスの重量を確認してください27 93648 53640 208
zend.use.model1.e.instance1Model1オブジェクトと$ eリンクの作成249246483432
zend.use.model1.f.instance2Model1オブジェクトの作成と$ fのリンク176432562488
zend.use.model1.g.instance3Model1オブジェクトと$ gリンクの作成176432562488
zend.use.model2.e.instance1Model2オブジェクトと$ eリンクの作成7401400944
zend.use.model2.f.instance2Model2オブジェクトと$ f参照の作成000


Gentooビルドが消費するメモリが10〜20%少ないことに気付くかもしれません。まれに、最大50%の節約になります。 どうやら、内部構造のサイズはプロセッサの最適化に依存します。 実験のために、さまざまなバージョンのCFLAGSを使用してphpを再構築しましたが、これ以上の消費は開始しませんでした。 どうやら、違いはPHP自体の再構築によるものではなく、標準のCisternライブラリの再構築によるものです。


上記のように、$ include_overheadを正確に測定することは難しいため、これらのテストを実行すると、同じものを消費するテストであっても、4、8、12、16バイトにジャンプするメモリ消費が発生する場合があります。 これに集中しないでください。 テストを異なる順序で実行し、実際のメモリ消費量を設定しました。

ZendFrameworkに関連するテストについて話しましょう。 Zendのクラス定義をメモリにロードすると、リソースが大量に消費されますが、オブジェクト参照はすでにそれほど消費していません。 Controller2は、すべての中間クラスが既にメモリ内にある場合に同様のコントローラーがどれだけ食べるかを確認するために必要です。 Model2は同じ目的で作成されます。
潜在的に、PHPアクセラレータを使用すると、すべての定義のメモリが節約されます。定義は既にメモリに格納されているためです。 このステートメントを確認しましょう。

加速器試験


APCはテスト用に取得され、テストはスクリプトを使用してWeb経由で実行されました。
 php run.testsuite-with-accelerator.php 

結果は、アクセラレータが効果を発揮するテストのみを示しています。
テスト名説明Ubuntu x86、
PHP 5.3.10、
ZF 1.11.11、
空のキャッシュ
Ubuntu x86、
PHP 5.3.10、
ZF 1.11.11、
リフレッシュ
Ubuntu x86-64、
PHP 5.3.10、
ZF 1.11.11、
空のキャッシュ
Ubuntu x86-64、
PHP 5.3.10、
ZF 1.11.11、
リフレッシュ
myclass.a.emptyクラスAの説明84067214801256
myclass.aa.interfaceインターフェイスの説明A85667615121264
myclass.ab.final最終クラスABの説明84467214881256
myclass.ac.abstractAC抽象クラスの説明85268015041264
myclass.b.extended.emptyAを拡張するクラスBの説明91270015121264
myclass.c.empty.namespace空の名前空間Cの説明176-16184-72
myclass.d.constructクラスDコンストラクターの説明125696024481736
myclass.dd.methodメソッドを使用したDDクラスの説明126896824321728
myclass.ddd.private.varプライベート変数を持つDDDクラスの説明11409642000年1760
myclass.dddd.public.varパブリック変数を持つDDDDクラスの説明11329522000年1760
myclass.ddddd.static.var静的変数を持つDDDDDクラスの説明11249522000年1760
myclass.e.extended.destructクラスDを拡張するデストラクタを持つクラスEの説明1528122828882160
myclass.z.free_memoryリンクの削除$ e、$ f-332-548-784-1024
zend.a.init.autoloadZendFrameworkの自動ロードを初期化する127 59616 196276,44028,992
zend.a.init.modelベースのデフォルトアダプターの初期化1 018 564251 8402 081 696479,280
zend.extended.controller1Zend_Controller_Actionからのコントローラー定義。 途中で、標準のZendクラスをロードします378,46466 804809 608120 864
zend.extended.controller2コントローラーの定義。 クラスZendはすでにロードされています。クラスの重量を確認します11 47611 14019 79219 056
zend.extended.model1Zend_Db_Tableによるモデル定義。 途中で、標準のZendクラスの読み込みが行われます。28,08025,67648,70442 944
zend.extended.model2モデルの定義。 Zendクラスは既にロードされています。クラスの重量を確認してください28,08025,70448,67242 960


また、xcacheでいくつかのテストを行い、APCとの2つの違いに気付きました。 まず、xcacheは(ほとんどの場合)メモリを10〜15%節約します。 次に、xcacheはキャッシュからファイルをすぐに返しますが、APCは繰り返しアクセスした後のみです。 役に立たないが、利点。


すぐに、ファイルの名前が変更されず、$ include_overheadが大きなエラーで計算されたため、結果のばらつきはアクセラレータなしでテストする場合よりもはるかに大きいことに注意してください。

ご覧のように、アクセラレータは定義のためにメモリを節約しますが、PHPがキャッシュから現在のセッションにいくつかのピースを転送するように見えるため、完全ではありません。
次に、抽象的なテストから実際のテストに移りましょう。

ZendFrameworkで小さなアプリケーションをテストする


テストのために、プログラマーの1人( Simple-blog )のテストタスクを行いました。機能は、登録、承認、投稿のリストの読み取り、投稿のオープン、コメント付きの機能を持つ集合ブログサービスです。 index.phpの最後に次のように書かれています:
 echo memory_get_peak_usage(); 
ページ生成中にスクリプトが消費したメモリ量を確認します。 結果:
ページの種類Ubuntu x86、
PHP 5.3.10、
ZF 1.11.11、
空のキャッシュ
Ubuntu x86、
PHP 5.3.10、
ZF 1.11.11、
リフレッシュ
Ubuntu x86-64、
PHP 5.3.10、
ZF 1.11.11、
空のキャッシュ
Ubuntu x86-64、
PHP 5.3.10、
ZF 1.11.11、
リフレッシュ
投稿リスト5 328 6481 792 96810 938 1603 306 720
投稿とコメント5 372 3561 831 45211 015 3203 373 528
ログインフォーム6 781 6562,277,16413 982 1044 187 600
登録フォーム6 796 4962,291,56814 009 3844 211 432

さらに、Gentooのアセンブリがテストされましたが、すべてのテストで25%の効果が得られました。

結論



コジャラ



UPD


AntonShevchukは 、PHP 5.4のテスト結果を追加しました。 PHP 5.4は5.3よりもはるかに経済的に見えます。 公式文書でもこれが確認されています。

Source: https://habr.com/ru/post/J161629/


All Articles