What are the effects of exceptions on performance in Java?

前端 未结 17 2344
情深已故
情深已故 2020-11-22 01:21

Question: Is exception handling in Java actually slow?

Conventional wisdom, as well as a lot of Google results, says that exceptional logic shouldn\'t be used for n

相关标签:
17条回答
  • 2020-11-22 01:32

    A while back I wrote a class to test the relative performance of converting strings to ints using two approaches: (1) call Integer.parseInt() and catch the exception, or (2) match the string with a regex and call parseInt() only if the match succeeds. I used the regex in the most efficient way I could (i.e., creating the Pattern and Matcher objects before intering the loop), and I didn't print or save the stacktraces from the exceptions.

    For a list of ten thousand strings, if they were all valid numbers the parseInt() approach was four times as fast as the regex approach. But if only 80% of the strings were valid, the regex was twice as fast as parseInt(). And if 20% were valid, meaning the exception was thrown and caught 80% of the time, the regex was about twenty times as fast as parseInt().

    I was surprised by the result, considering that the regex approach processes valid strings twice: once for the match and again for parseInt(). But throwing and catching exceptions more than made up for that. This kind of situation isn't likely to occur very often in the real world, but if it does, you definitely should not use the exception-catching technique. But if you're only validating user input or something like that, by all means use the parseInt() approach.

    0 讨论(0)
  • 2020-11-22 01:32

    Even if throwing an exception isn't slow, it's still a bad idea to throw exceptions for normal program flow. Used this way it is analogous to a GOTO...

    I guess that doesn't really answer the question though. I'd imagine that the 'conventional' wisdom of throwing exceptions being slow was true in earlier java versions (< 1.4). Creating an exception requires that the VM create the entire stack trace. A lot has changed since then in the VM to speed things up and this is likely one area that has been improved.

    0 讨论(0)
  • 2020-11-22 01:34

    Just compare let's say Integer.parseInt to the following method, which just returns a default value in the case of unparseable data instead of throwing an Exception:

      public static int parseUnsignedInt(String s, int defaultValue) {
        final int strLength = s.length();
        if (strLength == 0)
          return defaultValue;
        int value = 0;
        for (int i=strLength-1; i>=0; i--) {
          int c = s.charAt(i);
          if (c > 47 && c < 58) {
            c -= 48;
            for (int j=strLength-i; j!=1; j--)
              c *= 10;
            value += c;
          } else {
            return defaultValue;
          }
        }
        return value < 0 ? /* übergebener wert > Integer.MAX_VALUE? */ defaultValue : value;
      }
    

    As long as you apply both methods to "valid" data, they both will work at approximately the same rate (even although Integer.parseInt manages to handle more complex data). But as soon as you try to parse invalid data (e.g. to parse "abc" 1.000.000 times), the difference in performance should be essential.

    0 讨论(0)
  • 2020-11-22 01:41

    Why should exceptions be any slower than normal returns?

    As long as you don't print the stacktrace to the terminal, save it into a file or something similar, the catch-block doesn't do any more work than other code-blocks. So, I can't imagine why "throw new my_cool_error()" should be that slow.

    Good question and I'm looking forward to further information on this topic!

    0 讨论(0)
  • 2020-11-22 01:42

    I've done some performance testing with JVM 1.5 and using exceptions was at least 2x slower. On average: Execution time on a trivially small method more than tripled (3x) with exceptions. A trivially small loop that had to catch the exception saw a 2x increase in self-time.

    I've seen similar numbers in production code as well as micro benchmarks.

    Exceptions should definately NOT be used for anything that's called frequently. Throwing a thousands of exceptions a second would cause a huge bottle neck.

    For example, using "Integer.ParseInt(...)" to find all bad values in a very large text file--very bad idea. (I have seen this utility method kill performance on production code)

    Using an exception to report a bad value on a user GUI form, probably not so bad from a performance standpoint.

    Whether or not its a good design practice, I'd go with the rule: if the error is normal/expected, then use a return value. If it's abnormal, use an exception. For example: reading user inputs, bad values are normal--use an error code. Passing a value to an internal utility function, bad values should be filtered by calling code--use an exception.

    0 讨论(0)
  • 2020-11-22 01:44

    I changed @Mecki 's answer above to have method1 return a boolean and a check in the calling method, as you cannot just replace an Exception with nothing. After two runs, method1 was still either the fastest or as fast as method2.

    Here is snapshot of the code:

    // Calculates without exception
    public boolean method1(int i) {
        value = ((value + i) / i) << 1;
        // Will never be true
        return ((i & 0xFFFFFFF) == 1000000000);
    
    }
    ....
       for (i = 1; i < 100000000; i++) {
                if (t.method1(i)) {
                    System.out.println("Will never be true!");
                }
        }
    

    and results:

    Run 1

    method1 took 841 ms, result was 2
    method2 took 841 ms, result was 2
    method3 took 85058 ms, result was 2
    

    Run 2

    method1 took 821 ms, result was 2
    method2 took 838 ms, result was 2
    method3 took 85929 ms, result was 2
    
    0 讨论(0)
提交回复
热议问题