質問
PHP スクリプトをプロファイリングする最も簡単な方法は何ですか?
すべての関数呼び出しのダンプとその所要時間を表示するものを追加したいと思っていますが、特定の関数の周りに何かを追加することも問題ありません。
で実験してみました マイクロタイム 関数:
$then = microtime();
myFunc();
$now = microtime();
echo sprintf("Elapsed: %f", $now-$then);
しかし、それは時々私に否定的な結果をもたらします。さらに、それをコード全体に散りばめるのは非常に面倒です。
解決
の PECL APD 拡張子は次のように使用されます。
<?php
apd_set_pprof_trace();
//rest of the script
?>
その後、生成されたファイルを次を使用して解析します。 pprofp
.
出力例:
Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time = 0.00
Total User Time = 0.00
Real User System secs/ cumm
%Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0009 0 main
56.9 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0005 0.0005 0 apd_set_pprof_trace
28.0 0.00 0.00 0.00 0.00 0.00 0.00 10 0.0000 0.0000 0 preg_replace
14.3 0.00 0.00 0.00 0.00 0.00 0.00 10 0.0000 0.0000 0 str_replace
警告:APD の最新リリースは 2004 年です。 もう維持されていません さまざまな互換性の問題があります (コメントを参照)。
他のヒント
あなたが欲しいのは xデバッグ 私は思う。サーバーにインストールして電源を入れ、出力を送り込みます。 kcachegrind (Linux の場合) または ウィンキャッシュグラインド (Windows の場合) 正確なタイミング、カウント、メモリ使用量を詳細に示すいくつかの美しいグラフが表示されます (ただし、そのためには別の拡張機能が必要です)。
本当に素晴らしいよ :D
拡張機能は必要ありません。簡単なプロファイリングにはこれら 2 つの関数を使用するだけです。
// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
global $prof_timing, $prof_names;
$prof_timing[] = microtime(true);
$prof_names[] = $str;
}
// Call this when you're done and want to see the results
function prof_print()
{
global $prof_timing, $prof_names;
$size = count($prof_timing);
for($i=0;$i<$size - 1; $i++)
{
echo "<b>{$prof_names[$i]}</b><br>";
echo sprintf(" %f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
}
echo "<b>{$prof_names[$size-1]}</b><br>";
}
以下は、各チェックポイントで説明を指定して prof_flag() を呼び出し、最後に prof_print() を呼び出す例です。
prof_flag("Start");
include '../lib/database.php';
include '../lib/helper_func.php';
prof_flag("Connect to DB");
connect_to_db();
prof_flag("Perform query");
// Get all the data
$select_query = "SELECT * FROM data_table";
$result = mysql_query($select_query);
prof_flag("Retrieve data");
$rows = array();
$found_data=false;
while($r = mysql_fetch_assoc($result))
{
$found_data=true;
$rows[] = $r;
}
prof_flag("Close DB");
mysql_close(); //close database connection
prof_flag("Done");
prof_print();
出力は次のようになります。
始める
0.004303
DBに接続する
0.003518
クエリを実行する
0.000308
データの取得
0.000009
DBを閉じる
0.000049
終わり
オフラインになっている SO Documentation ベータ版からの私の参照をクロス投稿します。
XDebug を使用したプロファイリング
Xdebug と呼ばれる PHP の拡張機能は、次のことを支援するために利用できます。 PHP アプリケーションのプロファイリング, 、ランタイムデバッグも可能です。プロファイラを実行すると、出力は「cachegrind」と呼ばれるバイナリ形式でファイルに書き込まれます。これらのファイルを分析するためのアプリケーションが各プラットフォームで利用可能です。 このプロファイリングを実行するためにアプリケーション コードを変更する必要はありません。
プロファイリングを有効にするには、拡張機能をインストールし、php.ini 設定を調整します。一部の Linux ディストリビューションには標準パッケージが付属しています (例:Ubuntuの php-xdebug
パッケージ)。この例では、オプションでリクエスト パラメーターに基づいてプロファイルを実行します。これにより、設定を静的に保ち、必要な場合にのみプロファイラーをオンにすることができます。
# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let's use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"
次に、Web クライアントを使用して、プロファイリングしたいアプリケーションの URL にリクエストを送信します。
http://example.com/article/1?XDEBUG_PROFILE=1
ページが処理されると、次のような名前のファイルに書き込みます。
/tmp/cachegrind.out.12345
デフォルトでは、ファイル名の数字は、ファイルを書き込んだプロセス ID です。これは、 xdebug.profiler_output_name
設定。
実行される PHP リクエスト/プロセスごとに 1 つのファイルが書き込まれることに注意してください。したがって、たとえば、フォームの投稿を分析したい場合は、HTML フォームを表示するための GET リクエスト用のプロファイルが 1 つ作成されます。フォームを処理する 2 番目のリクエストを分析するには、XDEBUG_PROFILE パラメータを後続の POST リクエストに渡す必要があります。したがって、プロファイリングを行う場合、curl を実行してフォームを直接 POST する方が簡単な場合があります。
出力の分析
プロファイル キャッシュが書き込まれると、次のようなアプリケーションで読み取ることができます。 KCキャッシュグラインド または ウェブグラインド. 。人気の PHP IDE である PHPStorm も、 このプロファイリング データを表示します.
たとえば、KCachegrind は次のような情報を表示します。
- 実行された機能
- 呼び出し時間 (それ自体と後続の関数呼び出しを含む)
- 各関数が呼び出される回数
- コールグラフ
- ソースコードへのリンク
何を探すべきか
明らかに、パフォーマンスのチューニングは各アプリケーションの使用例に非常に固有です。一般に、次のものを探すとよいでしょう。
- 予期しない同じ関数への繰り返し呼び出し。データを処理およびクエリする関数の場合、これらはアプリケーションがキャッシュする絶好の機会となる可能性があります。
- 実行速度が遅い関数。アプリケーションはどこに最も多くの時間を費やしていますか?パフォーマンス チューニングで最も効果があるのは、最も時間を消費するアプリケーションの部分に焦点を当てることです。
注記:Xdebug、特にそのプロファイリング機能はリソースを非常に消費し、PHP の実行を遅くします。これらを運用サーバー環境では実行しないことをお勧めします。
マイクロタイムを減算すると負の結果が得られる場合は、引数を指定して関数を使用してみてください。 true
(microtime(true)
)。と true
, の場合、関数は文字列の代わりに浮動小数点を返します (引数なしで呼び出された場合と同様)。
正直に言うと、プロファイリングには NewRelic を使用するのが最善であると主張したいと思います。
これは PHP 拡張機能で、実行時間をまったく遅くすることはないようで、監視を行って適切なドリルダウンを可能にします。高価なバージョンでは、大幅なドリルダウンが可能です (ただし、価格モデルを買う余裕はありません)。
それでも、無料/標準プランであっても、簡単な成果のほとんどがどこにあるのかは明白かつ単純です。DB とのやり取りについてもアイデアを得ることができるのも気に入っています。
PECL XHPROF 見た目も面白そうです。それは持っています クリック可能なHTMLインターフェース レポートを表示するためのもので、非常に簡単です ドキュメンテーション. 。まだテストしていませんが。
可哀そうな人のプロファイリング、拡張機能は必要ありません。ネストされたプロファイルと合計の割合をサポートします。
function p_open($flag) {
global $p_times;
if (null === $p_times)
$p_times = [];
if (! array_key_exists($flag, $p_times))
$p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
$p_times[$flag]['open'] = microtime(true);
}
function p_close($flag)
{
global $p_times;
if (isset($p_times[$flag]['open'])) {
$p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
unset($p_times[$flag]['open']);
}
}
function p_dump()
{
global $p_times;
$dump = [];
$sum = 0;
foreach ($p_times as $flag => $info) {
$dump[$flag]['elapsed'] = $info['total'];
$sum += $info['total'];
}
foreach ($dump as $flag => $info) {
$dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
}
return $dump;
}
例:
<?php
p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');
var_dump(p_dump());
収量:
array:3 [
"foo" => array:2 [
"elapsed" => 9.000766992569
"percent" => 0.4736904954747
]
"bar" => array:2 [
"elapsed" => 7.0004580020905
"percent" => 0.36841864946596
]
"baz" => array:2 [
"elapsed" => 3.0001420974731
"percent" => 0.15789085505934
]
]
私はプロファイリングに phpDebug を使用するのが好きです。http://phpdebug.sourceforge.net/www/index.html
使用された SQL および含まれるすべてのファイルのすべての時間とメモリ使用量を出力します。明らかに、抽象化されたコードで最も効果的に機能します。
関数とクラスのプロファイリングには、単に使用します microtime()
+ get_memory_usage()
+ get_peak_memory_usage()
.
あなたの例のように、ベンチマークには、 梨のベンチマーク パッケージ。測定用のマーカーを設定します。このクラスにはいくつかのプレゼンテーション ヘルパーも用意されており、必要に応じてデータを処理できます。
実際には、__destruct メソッドを使用して別のクラスにラップしています。スクリプトが終了すると、出力が log4php 経由で syslog に記録されるため、作業に使用できるパフォーマンス データが大量にあります。
XDebug は安定していないため、特定の PHP バージョンで常に利用できるとは限りません。たとえば、一部のサーバーでは依然として php-5.1.6 を実行しています。これは RedHat RHEL5 に付属しているものです (ちなみに、すべての重要な問題についての更新はまだ受け取っています)。最近の XDebug はこの php でコンパイルすらしません。それで私は最終的にに切り替えることになりました DBGデバッガその PHPのベンチマーク 関数、メソッド、モジュール、さらには行のタイミングを提供します。