What are the effects of exceptions on performance in Java?

前端 未结 17 2342
情深已故
情深已故 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:45

    Don't know if these topics relate, but I once wanted to implement one trick relying on current thread's stack trace: I wanted to discover the name of the method, which triggered the instantiation inside the instantiated class (yeap, the idea is crazy, I totally gave it up). So I discovered that calling Thread.currentThread().getStackTrace() is extremely slow (due to native dumpThreads method which it uses internally).

    So Java Throwable, correspondingly, has a native method fillInStackTrace. I think that the killer-catch block described earlier somehow triggers the execution of this method.

    But let me tell you another story...

    In Scala some functional features are compiled in JVM using ControlThrowable, which extends Throwable and overrides its fillInStackTrace in a following way:

    override def fillInStackTrace(): Throwable = this
    

    So I adapted the test above (cycles amount are decreased by ten, my machine is a bit slower :):

    class ControlException extends ControlThrowable
    
    class T {
      var value = 0
    
      def reset = {
        value = 0
      }
    
      def method1(i: Int) = {
        value = ((value + i) / i) << 1
        if ((i & 0xfffffff) == 1000000000) {
          println("You'll never see this!")
        }
      }
    
      def method2(i: Int) = {
        value = ((value + i) / i) << 1
        if ((i & 0xfffffff) == 1000000000) {
          throw new Exception()
        }
      }
    
      def method3(i: Int) = {
        value = ((value + i) / i) << 1
        if ((i & 0x1) == 1) {
          throw new Exception()
        }
      }
    
      def method4(i: Int) = {
        value = ((value + i) / i) << 1
        if ((i & 0x1) == 1) {
          throw new ControlException()
        }
      }
    }
    
    class Main {
      var l = System.currentTimeMillis
      val t = new T
      for (i <- 1 to 10000000)
        t.method1(i)
      l = System.currentTimeMillis - l
      println("method1 took " + l + " ms, result was " + t.value)
    
      t.reset
      l = System.currentTimeMillis
      for (i <- 1 to 10000000) try {
        t.method2(i)
      } catch {
        case _ => println("You'll never see this")
      }
      l = System.currentTimeMillis - l
      println("method2 took " + l + " ms, result was " + t.value)
    
      t.reset
      l = System.currentTimeMillis
      for (i <- 1 to 10000000) try {
        t.method4(i)
      } catch {
        case _ => // do nothing
      }
      l = System.currentTimeMillis - l
      println("method4 took " + l + " ms, result was " + t.value)
    
      t.reset
      l = System.currentTimeMillis
      for (i <- 1 to 10000000) try {
        t.method3(i)
      } catch {
        case _ => // do nothing
      }
      l = System.currentTimeMillis - l
      println("method3 took " + l + " ms, result was " + t.value)
    
    }
    

    So, the results are:

    method1 took 146 ms, result was 2
    method2 took 159 ms, result was 2
    method4 took 1551 ms, result was 2
    method3 took 42492 ms, result was 2
    

    You see, the only difference between method3 and method4 is that they throw different kinds of exceptions. Yeap, method4 is still slower than method1 and method2, but the difference is far more acceptable.

提交回复
热议问题