この記事は、実稼働環境での PHP パフォーマンス テスト ツール xhprof の使用についての詳細な分析と紹介です。必要な方は参考にしてください。
xhprof は、Facebook によってオープンソース化された PHP パフォーマンス テスト ツールです。プロフィールツールと呼ばれますが、この言葉をどのように翻訳して意味を表現するかわかりません。以前使用していた xdebug と比較すると、多くの類似点があります。以前、参考になる xdebug の記録がいくつかありましたが、profiler_enable_trigger パラメータをオンにしても、本番環境で使用するとパフォーマンスに大きな影響を与えるという欠点がありました。 CPU はすぐに High に達します。
xhprof は非常に軽量で、プロファイルを記録するかどうかをプログラムで制御できるため、本番環境でも使用することが可能になります。そのような使用法はドキュメントで確認できます:
10,000 分の 1 の確率で xhprof を有効にし、通常は静かに撮影しません。
コードをコピーしますコードは次のとおりです:
if (mt_rand(1, 10000) == 1) {
xhprof_enable(XHPROF_FLAGS_MEMORY);
$xhprof_on = true;
}
コードをコピーします コードは次のとおりです:
if ($xhprof_on) {
// プロファイラーを停止します
$xhprof_data = xhprof_disable( );
// $xhprof_data をどこか (中央 DB など) に保存します
...
}
コードをコピーします コードは次のとおりです:
if (mt_rand(1, 10000) == 1) {
data;") ) ;
}
xhprof の使用改善に関するアイデア
xhprof が昨年本番環境で使用されて以来、本番環境でのプログラムのデバッグとパフォーマンスの最適化に非常に便利になりました。ただし、使用中に改善が必要な点がいくつかあります。
問題
xhprof のプロファイル ログは、ファイルの形式で運用サーバーに直接保存されます。ログを表示するには、定期的にクリーンアップするか、収集してツール マシンに移動する必要があります。 xhprof によって生成されたプロファイルは大きな配列であるため、ファイルに保存する際には標準の php シリアル化が使用され、ログ ファイルは比較的大きく、注意しないとサーバーのディスク領域を大量に占有する可能性があります。
ログリストを表示するときに、それぞれをクリックするのは困難です。
これらの質問に答えて、いくつかの小さなアイデアがあります。
ログストレージ
中央ログサーバーを展開し、Facebook のスクライブを使用してログを収集します。運用環境のサーバーによって生成された xhprof ログはスクライブ クライアントに書き込まれ、クライアントはローカル ストレージ領域を占有することなく、中央ログ サーバー上のスクライブに自動的に同期します。コードの変更も比較的小規模で、iXHProfRuns インターフェイスに基づいて XhprofRuns クラスを実装し、save_run メソッドのストレージ メソッドを調整するだけです。
シリアル化メソッドを変更する
xhprof のデフォルトでは、PHP のネイティブなシリアル化メソッドを使用してプロファイル情報を処理し、それを保存します。このテストでは、igbinary と Serialize と json_encode のパフォーマンスと占有率を比較しました。あらゆる面で利点があり、特に占有されるストレージ領域が大幅に削減されるため、シリアル化メソッドを igbinary_serialize に変更するだけで改善されます。
リスト表示を最適化する
プロフィールログの大きな画像を一つ一つ見るのは時間と労力がかかり、ターゲットを絞ったものではありません。そこで私が現在行っていることは、プロファイル ログのリストの最初の 1000 ログの全体の実行時間をリストに直接出力し、実行時間が長すぎるログを赤い太字でマークすることです。この小さな変更を加えた後は、動作状況を確認したいときに、ログリストの赤いリンクをクリックして確認するだけで済み、非常に時間と労力が節約されます。 xhprof ログファイルから実行時間を取得するには?簡単なコードは次のとおりです
コードをコピーしますコードは次のとおりです:
/**
* xhprof ログから実行時間を取得します
*
* @param string $log xhprof ログのファイルパス
* @return int 実行時間
*/
function getSpentTime($log) {
$profile = unserialize(file_get_contents) ($log));
$profile['main()']['wt'] / 1000;
}