PHP 5 で try-catch ステートメントを使用する場合、どのようなパフォーマンスへの影響を考慮する必要がありますか?
私は以前、このテーマに関する古くて矛盾しているように見える情報を Web で読んだことがあります。私が現在使用しなければならないフレームワークの多くは、php 4 で作成されたものであり、php 5 の優れた点の多くが欠けています。したがって、php で try-catch を使用した経験はあまりありません。
PHP 5 で try-catch ステートメントを使用する場合、どのようなパフォーマンスへの影響を考慮する必要がありますか?
私は以前、このテーマに関する古くて矛盾しているように見える情報を Web で読んだことがあります。私が現在使用しなければならないフレームワークの多くは、php 4 で作成されたものであり、php 5 の優れた点の多くが欠けています。したがって、php で try-catch を使用した経験はあまりありません。
考慮すべきことの 1 つは、例外がスローされない try ブロックのコストは、実際に例外をスローしてキャッチするコストとは別の問題であるということです。
失敗した場合にのみ例外がスローされる場合、プログラムの実行ごとに何度も失敗することはないため、ほぼ確実にパフォーマンスを気にする必要はありません。タイトなループ (レンガの壁に頭をぶつける) で失敗している場合、アプリケーションは遅くなるよりも悪い問題を抱えている可能性があります。したがって、例外をスローするコストについて心配する必要はありません。通常の制御フローで例外を使用する必要がある場合を除きます。
誰かが、例外をスローするプロファイリング コードについて話している回答を投稿しました。自分でテストしたことはありませんが、何もスローせずに try ブロックに出入りするよりも、はるかに大きなパフォーマンス ヒットが見られると自信を持って予測しています。
考慮すべきもう 1 つのことは、呼び出しを多くのレベルの深さでネストする場合、戻り値をチェックしてすべての呼び出しでエラーを伝播するよりも、一番上に単一の try...catch を配置する方が高速になる可能性があることです。
反対に、すべての呼び出しを独自の try...catch ブロックでラップしている場合、コードは遅くなります。そして醜い。
私は退屈で、次のプロファイルを作成しました(タイミングコードは省略しました)。
function no_except($a, $b) {
$a += $b;
return $a;
}
function except($a, $b) {
try {
$a += $b;
} catch (Exception $e) {}
return $a;
}
2 つの異なるループを使用します。
echo 'no except with no surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
no_except(5, 7);
}
echo 'no except with surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
try {
no_except(5, 7);
} catch (Exception $e) {}
}
echo 'except with no surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
except(5, 7);
}
echo 'except with surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
try {
except(5, 7);
} catch (Exception $e) {}
}
私のWinXPボックスで1000000回実行すると、ApacheとPHP 5.2.6が実行されます。
no except with no surrounding try = 3.3296
no except with surrounding try = 3.4246
except with no surrounding try = 3.2548
except with surrounding try = 3.2913
これらの結果は一貫しており、テストを実行した順序に関係なく、同様の割合を維持していました。
結論: まれな例外を処理するコードを追加することは、例外を無視するコードより遅くはありません。
一般に、例外を使用して予期しないエラーから保護し、通常のプログラム状態の一部であるエラーに対してコードでエラー チェックを使用します。説明する:
データベースにレコードが見つかりません - 有効な状態です。クエリの結果を確認し、ユーザーに適切にメッセージを送信する必要があります。
レコードを取得しようとしたときの SQL エラー - 予期しない失敗、レコードがある場合とない場合がありますが、プログラム エラーがあります - これは例外の適切な場所です - エラー ログにエラーを記録し、管理者にスタック トレースを電子メールで送信し、表示します何かがうまくいかず、あなたがそれに取り組んでいることをユーザーに知らせる丁寧なエラーメッセージ。
例外はコストがかかりますが、それらを使用してプログラム フロー全体を処理しない限り、パフォーマンスの違いは人間の目には見えません。
Google での Try/Catch パフォーマンスについては何も見つかりませんでしたが、IF ステートメントの代わりにループ スロー エラーを使用した単純なテストでは、5000 のループで 329 ミリ秒と 6 ミリ秒が生成されます。
非常に古いメッセージに投稿して申し訳ありませんが、コメントを読み、多少同意しません。単純なコードでは違いが最小限になるか、そうでないコードの特定の部分に Try/Catch が使用されている場合は無視できる可能性があります。常に予測可能ですが、単純なことも(テストされていませんが)信じています:
if(isset($var) && is_array($var)){
foreach($var as $k=>$v){
$var[$k] = $v+1;
}
}
よりも速い
try{
foreach($var as $k=>$v){
$var[$k] = $v+1;
}
}catch(Exception($e)){
}
また、次のことも信じています(テストされていません):
<?php
//beginning code
try{
//some more code
foreach($var as $k=>$v){
$var[$k] = $v+1;
}
//more code
}catch(Exception($e)){
}
//output everything
?>
コードに余分な IF があるよりも高価です
それはとても良い質問です!
何度もテストしましたが、パフォーマンスの問題は見られませんでした ;-) 10 年前は C++ でそうでした。
しかし、最初のエントリポイントをそれで囲むのはまだ怖いです:
try {Controller::run();}catch(...)
私はたくさんの関数呼び出しと大きなインクルードでテストしませんでした....誰かがすでにそれを完全にテストしていますか?
一般的に言えば、それらは高価であり、PHP では価値がありません。
これはチェック式言語であるため、例外をスローするものはすべてキャッチする必要があります。
スローしないレガシー コードとスローする新しいコードを扱う場合、混乱を招くだけです。
幸運を!