「例外のキャッチ」を使用して読みやすさを向上させる、良いか悪いか?


9

セクションで使用例外にする場合実用的プログラマー、代わりのブックへの書き込み:

retcode = OK;
     if (socket.read(name) != OK) {
      retcode = BAD_READ;
    }
     else {
      processName(name);
       if (socket.read(address) != OK) {
        retcode = BAD_READ;
      }
       else {
        processAddress(address);
         if (socket.read(telNo) != OK) {
          retcode = BAD_READ;
        }
         else {
          //  etc, etc...
        }
      }
    }
     return retcode;

、 彼らは好む:

 retcode = OK;
     try {
      socket.read(name);
      process(name);
      socket.read(address);
      processAddress(address);
      socket.read(telNo);
      //  etc, etc...
    }
     catch (IOException e) {
      retcode = BAD_READ;
      Logger.log( "Error reading individual: " + e.getMessage());
    }
     return retcode;

見た目がすっきりしているからです。私はすべてコードがすっきりしていますが、例外を不必要にキャッチすることがパフォーマンスのボトルネックになりませんか?

きちんとしたコード(少なくとも99%の時間)のごくわずかな最適化をあきらめる必要があることは理解できますが、私が知っていることから、例外の捕捉は、実行時に顕著な遅延があるコードのクラスに属しています。したがって、最初のコードよりも2番目のコードが優先される理由は何なのかと思っていました。

または、どちらのコードを使用しますか?


コードレビューの質問ではなくベストプラクティスの質問であるため、コードレビューから移行しました
Winston Ewert

1
IMO、あなたが期待している場合は、ソケットからそれらvaluseを読むことができるように、そしてIOExがある例外。
Steven Evers

このディスカッションに関連:例外以外のものにThrowableを使用する
Daniel R Hicks

測定しましたか?

@ThorbjørnRavnAndersenもちろん本を読んでいて、測定するための実際の「テストケース」はありませんが、人為的なコードで測定すると、明らかにパフォーマンスペナルティがあります
Pacerier

回答:


18

例外は通常、実際にスローされた場合にのみ遅くなります。通常、このような状況での例外はまれであるため、心配する必要はありません。例外が常に発生していて、それが重要な要素である場合にのみ、例外のパフォーマンスについて本当に心配する必要があります。

2番目のコードは、ロジックをたどるのがはるかに簡単なので、より優れています。エラー処理はうまくローカライズされています。唯一の異論は、例外を使用している場合は例外を使用することです。例外をキャッチしてエラーコードを返さないでください。


4
同意すると、例外のある言語でエラーコードが表示されるのが嫌いです。ほとんどの場合、呼び出しスタック壊すことなく、キャッチ、ログ、再スローする必要があります。そして、ほとんどの場合、「例外」のケースが遅いかどうかは問題ではありません。アプリに問題があります。時間をかけて正しく処理してください。例外が例外的であり、アプリケーションの通常の操作、またはハッピーパスの一部でない限り、通常はコードのにおいではありません。
CaffGeek

ところで、docs.oracle.com / javase / tutorial / essential / io / datastreams.htmlに示されているように、DataStreamsが行末を検出するために使用するEOFException(行末は例外ではありません)をどのように正当化するのか疑問に思っていました
Pacerier

@Pacerier、それは例外かもしれません。行の入力が不足している場合は、不良データまたは何かがひどく間違っていることを示している可能性があります。私は、意図された使用が行からいくつかのフィールドを解析することであると思います。
Winston Ewert

@Downvoter、回答に問題がある場合は、説明してください!
Winston Ewert、2011

5

まあ、彼らも言うように、例外は例外的なケースを処理する必要があります。これは例外的なケース(つまり、ほとんど発生しないもの)であるため、これはここでも当てはまると思います。

また、このようなことをマイクロ最適化しないことをお勧めます。新しいコードを書くよりもコードを読むのにはるかに多くの時間を費やすことになるので、コードの読みやすさにもっと焦点を合わせてください。

これがパフォーマンスのボトルネックであることを本当に確認するには、プロファイリングを行い、その分析に基づいて、より重要なタスクを分析して焦点を当てます。


5

きちんとしたコード(少なくとも99%の時間)のごくわずかな最適化をあきらめる必要があることは理解できますが、私が知っていることから、例外の捕捉は、実行時に顕著な遅延があるコードのクラスに属しています。

どこからそれを知っていますか?「顕著な遅延」をどのように定義しますか?

これはまさに、役に立たない時期尚早な最適化につながる、漠然とした(そして完全に間違った)パフォーマンスの神話です。

例外のスローとキャッチは、2つの数値を加算するのに比べて遅い場合がありますが、ソケットからのデータの読み取りと比較すると、まったく意味がありません。おそらく、1つのネットワークパケットを読み取っているのと同時に、1,000の例外をスローしてキャッチすることができます。ここでは、数千の例外について話しているのではなく、1つの例外についてのみ話します。


..私はそうジャワの私の知識恩赦.NETから来るが、私は個人的に「キャッチ・例外コード」を除去することにより、固定した非常識な遅延(秒の大きさ)を引き起こす.NETで例外をキャッチ経験している
Pacerier

@Pacerier、真剣に?秒の大きさ?多分それは多くの例外をキャッチしていたと思いますか?それから私はそれを見ることができました。
Winston Ewert

3
@Pacerier:例外が異常な遅延を引き起こしている場合、それらの原因が例外ではないことは明らかなので、他の方法で処理する必要があります。例外を処理するのに数秒かかるシステムはありません。Microsoftはそれを回避するのに十分な能力があると思います。
デビッド・ソーンリー

5

これは例外的なケースであり、例外処理を使用するのが合理的であると既に得ている答えに同意します。

パフォーマンスの問題にもっと直接対処するには、物事についてスケール感を保つ必要があると思います。このような状況で例外をスロー/キャッチすると、1マイクロ秒程度かかる可能性があります。フロー制御が進むにつれ、それはだん遅く -何回も遅く、通常よりもif文、そのことについては疑問。

同時に、ここで行うのはネットワークからデータを読み取ることです。1秒あたり10メガビット(ローカルネットワークの場合は低速ですが、インターネット接続ほど高速です)では、1バイトの情報を読み取る時間と同じです。

もちろん、そのオーバーヘッドは、実際に例外をスローした場合にのみ発生します。例外がスローされない場合、オーバーヘッドはほとんどまたはまったくありません(少なくとも、私が見た限りでは、最も重要なオーバーヘッドは、潜在的な制御フローを追加することによる例外処理自体、コンパイラーがコードを最適化することも困難になります)。

この場合、例外がスローされると、データがログに書き込まれます。ロギングの性質を考えると、書き込むときにすぐにその出力をフラッシュする可能性はかなり高いです(失われないようにするため)。ディスクへの書き込みは(繰り返しますが)非常に遅い操作です。1秒あたり数万のIOPの範囲に入るには、かなり高速なエンタープライズクラスのSSDが必要です。ロギングに使用されるディスクは、数百IOP /秒のようなものに簡単に制限される場合があります。

結論:例外処理のオーバーヘッド大きくなる場合があります、これはほぼ間違いなくその1つではありません

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.