web-dev-qa-db-ja.com

Javascriptでは、例外がスローされない場合でもtry-catchブロックを使用するのは高価ですか?

例外がスローされないときにいくつかのtry-catchブロックを使用するのは「遅い」ですか?私の質問は this one と同じですが、Javascriptについてです。

Try-catchブロックが含まれる20個の関数があるとします。そして、これらの20個の関数をすべて呼び出す別の関数。それらのいずれも例外をスローしません。このtry-catchブロックが原因で、コードの実行速度が低下したり、パフォーマンスが低下したりしますか?

48
cprcrack

典型的なCRUD UIコードをやっていますか? try catchesを使用し、コードに散りばめられた理由もなく10000に達するループを使用します。

低レベルのライブラリ、物理シミュレーション、ゲーム、サーバーサイドなどを実行している場合、通常はスローしないtry-catchブロックはまったく問題になりませんが、問題はV8がバージョン6まで最適化コンパイラーでそれをサポートしなかったことですしたがって、構文的にtry catchを含む包含関数全体は最適化されません。ただし、tryCatchのようなヘルパー関数を作成することで、この問題を簡単に回避できます。

function tryCatch(fun) {
    try {
        return fun();
    }
    catch(e) {
        tryCatch.errorObj.e = e;
        return tryCatch.errorObj;
    }
}
tryCatch.errorObj = {e: null};


var result = tryCatch(someFunctionThatCouldThrow);
if(result === tryCatch.errorObj) {
    //The function threw
    var e = result.e;
}
else {
    //result is the returned value
}

V8バージョン6(Node 8.3および最新のChromeに付属)の後、try-catch内のコードのパフォーマンスは通常のコードのパフォーマンスと同じです。

48
Esailija

元の質問では、エラーがスローされなかった場合のtry/catchのコストについて尋ねました。 try/catchを使用してコードブロックを保護する場合、確実に影響がありますが、保護されるコードが少し複雑になると、try/catchの影響はすぐに消えます。

このテストを検討してください: http://jsperf.com/try-catch-performance-jls/2

単純な増分は、毎秒356,800,000反復で実行されます。try/ catch内の同じ増分は、毎秒93,500,000反復です。 try/catchによるオーバーヘッドは75%です。しかし、些細な関数呼び出しは毎秒112,200,000回の繰り返しで実行されます。 2つの簡単な関数呼び出しは、1秒あたり61,300,000の繰り返しで実行されます。

このテストでの未実行の試行は、1つの単純な関数呼び出しよりもわずかに時間がかかります。これは、FFTのような非常に激しいものの最も内側のループを除き、重要な速度の低下ではありません。

回避したいケースは、実際に例外がスローされるケースです。上記のリンクに示すように、これは非常に遅くなります。

編集:これらの数値はChrome私のマシン上。Firefoxでは、未実行の試行と保護なしの間に大きな違いはありません。例外がなければtry/catchを使用しても基本的にペナルティはありません。投げた。

36
asthomas

try-catchブロックは高価であると言われています。ただし、重要なパフォーマンスが問題にならない場合、それを使用することは必ずしも問題ではありません。

ペナルティIMOは次のとおりです。

  • 読みやすさ
  • 多くの場合不適切
  • 非同期プログラミングに関しては効果がない

読みやすさ:大量のtry-catchでコードを配管するのはくて気が散る

inappropriate:コードが例外クラッシュの影響を受けない場合、そのようなブロックを挿入するのは悪い考えです。コードの失敗が予想される場合にのみ挿入してください。次のトピックをご覧ください。 try/catchブロックを使用するタイミング?

Asynctry-catchブロックは同期的であり、asyncプログラミングに関しては効果的ではありません。 ajaxリクエスト中に、専用のコールバックでerrorイベントとsuccessイベントの両方を処理します。 try-catchは必要ありません。

お役に立てれば、

R.

7
roland