try-catchは遅い

例外の処理は非常に遅い処理です。

例外を投げること、tryブロックで囲み補足すること自体は問題ありませんが、使い方に気を付けないと深刻なパフォーマンス低下を引き起こすことがあります。

極端に悪い例として、ループを抜けるための判定処理をtry-catchを用いて実装したものを示します。

C++
// 自然数の数列の和を計算する
// includeやmain()関数は省略

std::vector<int> vec(10000);
std::iota(vec.begin(), vec.end(), 1);

int i = 0;
long sum = 0;

while(1) {
    try { 
        sum += vec.at(i);
        i++;
    } catch (std::out_of_range) {
        break;
    }
}

このコード自体は正常に動作しますが、問題は範囲外例外(std::out_of_range)が必ず起こるということです。例外をcatchしループを抜ける処理はかなり遅いため、この場合は必ず重いcatch処理が発生することになります。

仮にこの処理自体が繰り返し呼ばれるような場合、致命的なパフォーマンス低下となることがあります。

今回であれば当然ですが無限ループではなく範囲forで書くべきです。

C++
for(auto val : vec) {
    sum += val;
}

ソフトの開発方針や言語、環境にもよりますが、例外処理機構を使うこと自体は間違っていません。ただし重い処理であることを認識し、頻繁に発生するような場合や繰り返し呼ばれるような処理では注意が必要です。

  • 必ず(あるいは頻繁に)起こるような事象を例外で処理しようとしない
    • ifで処理できるなら例外処理を使わない
    • コーディングの工夫で例外が極力発生しないようにする
  • 繰り返し呼ばれる処理では必要性を十分に検証する

コメント

タイトルとURLをコピーしました