9

In the section When to Use Exception in The Pragmatic Programmer, the book writes that instead of:

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;

, they prefer:

 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;

simply because it looks neater. I'm all for neater code, however isn't unnecessary catching of Exceptions a performance bottleneck?

I can understand that we should give up minuscule optimization for neater code (at least 99% of the times), however from what I know, catching exceptions belong to the class of code which have a noticeable delay in runtime. Hence I was wondering what's the justification that the second piece of code is preferred over the first code?

Or rather, which code would you prefer?

6
  • migrated from Code Review because its a best-practice question not a code review question Nov 4, 2011 at 13:27
  • 1
    IMO, if you are expecting to be able to read those valuse from the socket, then an IOEx is exceptional. Nov 4, 2011 at 13:36
  • Relevant to this discussion: Using Throwable for Things Other than Exceptions Nov 5, 2011 at 22:43
  • Have you measured?
    – user1249
    Nov 6, 2011 at 17:21
  • @ThorbjørnRavnAndersen of course I was reading the book and don't have a real "test case" to measure.. but if we do measure it in a contrived code then obviously there's a performance penalty then
    – Pacerier
    Nov 8, 2011 at 7:04

4 Answers 4

18

Exceptions are typically only slower if they actually thrown. Usually, the exceptions in situations like this are rare so its not something you should worry about. You should only really worry about the performance of exceptions if they are happening all the time and thus are a significant factor.

The second code is better because its much easier to follow the logic. The error handling is nicely localised. The only objection is that if you are using exceptions, then use exceptions. Don't catch the exceptions and then return an error code.

4
  • 4
    Agreed, I hate seeing error codes in a language that has exceptions. Most of the time you should catch, log, rethrow without breaking the call stack. And most of the time, it doesn't matter if an "exception" case is slower. The app has an issue, take the time to handle it properly. As long as the exception is exceptional, and not part of the normal operation, or happy path, of the application, it's not usually a code smell.
    – CaffGeek
    Nov 4, 2011 at 13:36
  • Btw I was wondering how do we justify the EOFException which DataStreams uses to detect an end of line (end of line isn't exceptional is it) as demonstrated in docs.oracle.com/javase/tutorial/essential/io/datastreams.html ?
    – Pacerier
    Nov 12, 2011 at 5:19
  • @Pacerier, it could be exceptional. Running out of input in the line could indicate bad data or something going horribly wrong. I suspect the intended use is to parse several fields out of a line. Nov 12, 2011 at 15:46
  • @Downvoter, if you have a problem with answer, please explain! Dec 1, 2011 at 17:51
5

Well, as they also say, exceptions should handle the exceptional cases, and since this is an exceptional case (i.e. something that happens few and far in between) I'd say that this applies here as well.

Also, I'd advise against micro-optimizing things such as this. Focus more on the readability of the code, since you'll be spending far more time reading code than writing new code.

To really make sure that this is a performance bottleneck, do some profiling, and analyze and focus on the more critical tasks based on that analysis.

5

I can understand that we should give up minuscule optimization for neater code (at least 99% of the times), however from what I know, catching exceptions belong to the class of code which have a noticeable delay in runtime.

Where do you know that from? How do you define "noticeable delay"?

This is exactly the kind of vague (and completely wrong) performance myth that leads to useless premature optimizations.

Throwing and catching an exception may be slow compared to adding two numbers, but it's completely insignificant compared to reading data from a socket. You could probably throw and catch a thousand exceptions in the same time you've read a single network packet. And we're not talking about thousands of exceptions here, only a single one.

3
  • I come from .NET so pardon my knowledge of Java, but I have personally experienced catching exceptions in .NET causing insane delays (magnitude of seconds) which were fixed by removing "catching-exception code"..
    – Pacerier
    Nov 4, 2011 at 15:21
  • @Pacerier, seriously? magnitude of seconds? I guess maybe it was catching lots of exceptions? Then I could see that. Nov 4, 2011 at 18:48
  • 3
    @Pacerier: If exceptions are causing insane delays, clearly what's causing them isn't exceptional, and therefore should be handled in other ways. No system should take seconds to process an exception, and I think Microsoft's sufficiently competent to avoid that. Nov 4, 2011 at 19:20
5

I'd agree with the answers you've already gotten saying that this is an exceptional case, so it's reasonably to use exception handling.

Addressing your performance concerns more directly, I think you need to keep a sense of scale about things. Throwing/catching an exception under these circumstances is likely to take one the order of a microsecond. As flow control goes, that's slow -- many times slower than normal if statements, no question about that.

At the same time, keep in mind that what you're doing here is reading data from a network. At 10 megabits per second (slow for a local network, but pretty fast as Internet connections go), that's on the same order as the time to read one byte of information.

Of course, that overhead is only incurred when you actually throw the exception as well -- when it's not thrown, there's usually little or no overhead at all (at least from what I've seen, the most significant overhead isn't from the exception handling itself, as from adding more potential flows of control, making the code harder for the compiler to optimize quite as well).

In this case, when an exception is thrown, your writing data to the log. Given the nature of logging, chances are pretty good that your flushing that output as soon as you write it (to ensure it isn't lost). Writing to disk is (again) quite a slow operation -- you need a fairly fast enterprise-class SSD to even get into the range of tens of thousands of IOPs/second. A disk used for logging might easily be limited to something like hundreds of IOPs/second.

Bottom line: there are cases where exception handling overhead can be significant, but this almost certainly is not one of them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.