BaiduのエンジニアはPHP関数の実現原理と性能分析(二)を話しています。


クラスの方法
クラスの方法は、その実行原理とユーザー関数は同じであり、opcodesに訳されて順番に呼び出される。クラスの実装は、zedは一つのデータ構造でzend_クラスentryは実現に来て、中は種類の関連しているいくつかの基本的な情報を保存しました。このイベントはphpでコンパイルする時に処理が完了しました。
ゼドドドにあるfunctionのcommonの中には、scopeというメンバーがいますが、それは現在の方法に対応する種類のzend_を指しています。クラスentryphpにおけるオブジェクト指向の実現については、ここでは詳しく紹介していませんが、今後はphpにおけるオブジェクト指向の実現原理について、専門的に文章を書きます。関数のこのブロックについては、methodは原理とfunctionが全く同じで、理論的にはその性能も似ています。
性能の比較
関数名の長さが性能に及ぼす影響
』のテスト方法は、名前の長さが1、2、4、8、16の関数を比較し、それらの毎秒実行可能回数を比較し、関数名の長さが性能に及ぼす影響を決定します。
』のテスト結果は下図の通りです。
02.jpg
』の結果分析
図から、関数名の長さは性能に影響を与えるかどうかが分かります。長さ1の関数と長さ16の空関数呼び出しは、性能が1倍の差があります。ソースを分析してみてください。前に述べたように、関数が呼び出された時に、まずグローバルのfuntion_にあります。テーブルで関数名で関連情報を検索します。テーブルはハッシュ・テーブルである。もちろん、名前が長いほど、調べに必要な時間が多くなります。そのため、実際にプログラムを作成する際には、何度も呼び出した関数に対して、名前はあまり長くしないようにしてください。
関数名の長さは性能に影響がありますが、具体的にはどれぐらいですか?この問題はやはり実際の状況に合わせて考える必要があります。一つの関数自体が複雑であれば、全体の性能にはあまり影響がありません。一つの提案は、それらが何回も呼び出されます。自分の機能は比較的簡単な関数です。適切にいくつかの簡単な名前を取ってもいいです。
関数の個数が性能に及ぼす影響
』試験方法
次の3つの環境で関数コールテストを行います。分析結果:1.プログラムは1つの関数2のみを含みます。プログラムは100の関数3.プログラムは1000の関数を含みます。この3つのケースをテストします。毎秒の関数の数を指定します。
』のテスト結果は下図の通りです。
03.jpg
』の結果分析
試験結果から,これらの3つの場合は性能がほぼ同じで,関数の個数が増加すると性能がわずかに低下し,無視できることが分かった。実施原理解析から、いくつかの実装における唯一の違いは、関数取得の部分にある。前に述べたように、すべての関数は一つのshテーブルにおいて、検索効率は異なる数でもO(1)に近いはずですので、性能の差はあまりありません。
異なるタイプの関数呼び出しの消費
』試験方法
ユーザ関数、クラス方法、静的方法、内蔵関数の各種類を選択します。関数自体は何もしないで、直接戻ります。主に空関数呼び出しの消耗をテストします。試験結果は、毎秒実行可能な回数テストで、他の影響を除くため、すべての関数の名前の長さが同じです。
』のテスト結果は下図の通りです。
』の結果分析
テスト結果によって、ユーザーが自分で作成したphp関数に対して、どのタイプでも効率は同じで、280 w/sぐらいです。エアコンでも内部関数の効率が高く、780 w/sに達すると予想されています。前者は3倍です。表示されるように、内蔵関数の呼び出しのオーバーヘッドは、ユーザ関数よりも遥かに低いです。前の原理分析から、主な違いはユーザー関数の呼び出し時にシンボル表を初期化したり、パラメータを受信したりすることです。
内蔵関数とユーザー関数の性能比較
』試験方法
内蔵関数とユーザー関数の性能コントラストはここでいくつかの一般的な関数を選択して,phpで同じ機能の関数を実現して性能比較を行った。テストでは、文字列、数学、配列のそれぞれの典型的な比較を選択します。これらの関数はそれぞれ文字列切り取り(substr)、10進数回転2進数(decbin)、最小値(min)とリターン配列の中のkeyです。keys
』のテスト結果は下図の通りです。
30-1.jpg
』の結果分析
テスト結果から,我々が期待するように,内蔵関数は全体的な性能では通常のユーザー関数よりもはるかに高いことがわかった。特に文字列クラスの操作に関わる関数については、1桁の差があります。したがって、関数の使用の原則は、ある機能に該当する内蔵関数があれば、できるだけ自分でphp関数を作成するのではなく、それを使用することです。多数の文字列動作に関連する機能のいくつかについては、性能を向上させるために、拡張で実現することが考えられます。よくあるリッチテキストフィルタなどです。
C関数との性能比較
』試験方法
文字列操作と算術演算の各3種類の関数を比較し,phpを拡張で実現した。3つの関数は、単純なアルゴリズム演算、文字列比較、および複数のアルゴリズム演算です。自身の2種類の関数以外に、関数のエアコンのオーバーヘッドを取り除いた後の性能をテストして、一方は2種類の関数(cとphp内蔵)の自身の性能の違いを比べて、その他に側面の印のエアコンの関数の消耗のテスト点は10 w回の操作を実行する時間の消耗です。
』のテスト結果は下図の通りです。
30-2.jpg
』の結果分析
内蔵関数とC関数のオーバーヘッドは、php関数のエアコン使用の影響を除くと差が小さくなり、関数機能が複雑になるにつれて、両者の性能は同じに近くなります。これは前の関数実現分析からも簡単に論証されます。つまり、内蔵関数はCで実現されます。関数機能が複雑になればなるほど、cとphpの性能差が小さくなる相対cにとって、php関数呼び出しのオーバーヘッドが大きくなり、簡単な関数にとっては性能に影響があります。したがって、phpの関数は、パッケージの深さを入れ替えるべきではない。
疑似関数とその性能
phpでは、使用上は標準的な関数の使用法であるが、下の実装と実際の関数の呼び出しは全く違っていて、これらの関数は前の文で述べた3つのfunctionのうちのいずれにも該当しない。実質は単独のopcodeであり、ここでは、擬似関数または命令関数と呼ばれている。
上記のように、疑似関数は標準の関数と同じような特徴を持つように見える。しかし、彼らが最終的に実行する時は、zedによって対応するコマンド(opcode)に反映されて呼び出されるので、if、for、算術演算などの操作に近い実現が可能です。
』phpの疑似関数
isset
empty
unset
エバー
上記の説明により、疑似関数は命令に直接翻訳されて実行されるので、一次関数呼び出しによるオーバーヘッドが一般関数に比べて少なくなり、性能がより良いことが分かります。私たちは次のテストを通して比較をします。Aray_key_existsとissetの両方は配列の中にあるkeyが存在するかどうかを判断できます。彼らの性能を見てください。
30-3.jpg
図から分かるように、array_とkey_existsに比べてissetの性能はかなり高くて、基本的に前者の4倍ぐらいです。空の関数の呼び出しに比べても、その性能は1倍ぐらい高いです。これにより、php関数呼び出しのオーバヘッドが大きいことをサイドプリントして再度説明した。