65

PHP 5 で try-catch ステートメントを使用する場合、どのようなパフォーマンスへの影響を考慮する必要がありますか?

私は以前、このテーマに関する古くて矛盾しているように見える情報を Web で読んだことがあります。私が現在使用しなければならないフレームワークの多くは、php 4 で作成されたものであり、php 5 の優れた点の多くが欠けています。したがって、php で try-catch を使用した経験はあまりありません。

4

9 に答える 9

72

考慮すべきことの 1 つは、例外がスローされない try ブロックのコストは、実際に例外をスローしてキャッチするコストとは別の問題であるということです。

失敗した場合にのみ例外がスローされる場合、プログラムの実行ごとに何度も失敗することはないため、ほぼ確実にパフォーマンスを気にする必要はありません。タイトなループ (レンガの壁に頭をぶつける) で失敗している場合、アプリケーションは遅くなるよりも悪い問題を抱えている可能性があります。したがって、例外をスローするコストについて心配する必要はありません。通常の制御フローで例外を使用する必要がある場合を除きます。

誰かが、例外をスローするプロファイリング コードについて話している回答を投稿しました。自分でテストしたことはありませんが、何もスローせずに try ブロックに出入りするよりも、はるかに大きなパフォーマンス ヒットが見られると自信を持って予測しています。

考慮すべきもう 1 つのことは、呼び出しを多くのレベルの深さでネストする場合、戻り値をチェックしてすべての呼び出しでエラーを伝播するよりも、一番上に単一の try...catch を配置する方が高速になる可能性があることです。

反対に、すべての呼び出しを独自の try...catch ブロックでラップしている場合、コードは遅くなります。そして醜い。

于 2008-09-19T18:58:02.090 に答える
57

私は退屈で、次のプロファイルを作成しました(タイミングコードは省略しました)。

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

これらの結果は一貫しており、テストを実行した順序に関係なく、同様の割合を維持していました。

結論: まれな例外を処理するコードを追加することは、例外を無視するコードより遅くはありません。

于 2009-01-14T23:28:00.257 に答える
9

一般に、例外を使用して予期しないエラーから保護し、通常のプログラム状態の一部であるエラーに対してコードでエラー チェックを使用します。説明する:

  1. データベースにレコードが見つかりません - 有効な状態です。クエリの結果を確認し、ユーザーに適切にメッセージを送信する必要があります。

  2. レコードを取得しようとしたときの SQL エラー - 予期しない失敗、レコードがある場合とない場合がありますが、プログラム エラーがあります - これは例外の適切な場所です - エラー ログにエラーを記録し、管理者にスタック トレースを電子メールで送信し、表示します何かがうまくいかず、あなたがそれに取り組んでいることをユーザーに知らせる丁寧なエラーメッセージ。

例外はコストがかかりますが、それらを使用してプログラム フロー全体を処理しない限り、パフォーマンスの違いは人間の目には見えません。

于 2008-09-19T18:36:04.470 に答える
5

Google での Try/Catch パフォーマンスについては何も見つかりませんでしたが、IF ステートメントの代わりにループ スロー エラーを使用した単純なテストでは、5000 のループで 329 ミリ秒と 6 ミリ秒が生成されます。

于 2008-09-19T18:35:45.657 に答える
3

非常に古いメッセージに投稿して申し訳ありませんが、コメントを読み、多少同意しません。単純なコードでは違いが最小限になるか、そうでないコードの特定の部分に 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 があるよりも高価です

于 2012-10-08T16:29:07.663 に答える
1

それはとても良い質問です!

何度もテストしましたが、パフォーマンスの問題は見られませんでした ;-) 10 年前は C++ でそうでした。

しかし、最初のエントリポイントをそれで囲むのはまだ怖いです:

try {Controller::run();}catch(...)

私はたくさんの関数呼び出しと大きなインクルードでテストしませんでした....誰かがすでにそれを完全にテストしていますか?

于 2009-12-03T11:43:34.860 に答える
-9

一般的に言えば、それらは高価であり、PHP では価値がありません。

これはチェック式言語であるため、例外をスローするものはすべてキャッチする必要があります。

スローしないレガシー コードとスローする新しいコードを扱う場合、混乱を招くだけです。

幸運を!

于 2008-09-19T18:31:57.020 に答える