Which part of throwing an Exception is expensive?

后端 未结 6 2028
盖世英雄少女心
盖世英雄少女心 2020-11-30 16:52

In Java, using throw/catch as a part of logic when there\'s not actually an error is generally a bad idea (in part) because throwing and catching an exception is expensive,

6条回答
  •  再見小時候
    2020-11-30 17:16

    The creation of the Exception with a null stack trace takes about as much time as the throw and try-catch block together. However, filling the stack trace takes on average 5x longer.

    I created the following benchmark to demonstrate the impact on performance. I added the -Djava.compiler=NONE to the Run Configuration to disable compiler optimization. To measure the impact of building the stack trace, I extended the Exception class to take advantage of the stack-free constructor:

    class NoStackException extends Exception{
        public NoStackException() {
            super("",null,false,false);
        }
    }
    

    The benchmark code is as follows:

    public class ExceptionBenchmark {
    
        private static final int NUM_TRIES = 100000;
    
        public static void main(String[] args) {
    
            long throwCatchTime = 0, newExceptionTime = 0, newObjectTime = 0, noStackExceptionTime = 0;
    
            for (int i = 0; i < 30; i++) {
                throwCatchTime += throwCatchLoop();
                newExceptionTime += newExceptionLoop();
                newObjectTime += newObjectLoop();
                noStackExceptionTime += newNoStackExceptionLoop();
            }
    
            System.out.println("throwCatchTime = " + throwCatchTime / 30);
            System.out.println("newExceptionTime = " + newExceptionTime / 30);
            System.out.println("newStringTime = " + newObjectTime / 30);
            System.out.println("noStackExceptionTime = " + noStackExceptionTime / 30);
    
        }
    
        private static long throwCatchLoop() {
            Exception ex = new Exception(); //Instantiated here
            long start = System.currentTimeMillis();
            for (int i = 0; i < NUM_TRIES; i++) {
                try {
                    throw ex; //repeatedly thrown
                } catch (Exception e) {
    
                    // do nothing
                }
            }
            long stop = System.currentTimeMillis();
            return stop - start;
        }
    
        private static long newExceptionLoop() {
            long start = System.currentTimeMillis();
            for (int i = 0; i < NUM_TRIES; i++) {
                Exception e = new Exception();
            }
            long stop = System.currentTimeMillis();
            return stop - start;
        }
    
        private static long newObjectLoop() {
            long start = System.currentTimeMillis();
            for (int i = 0; i < NUM_TRIES; i++) {
                Object o = new Object();
            }
            long stop = System.currentTimeMillis();
            return stop - start;
        }
    
        private static long newNoStackExceptionLoop() {
            long start = System.currentTimeMillis();
            for (int i = 0; i < NUM_TRIES; i++) {
                NoStackException e = new NoStackException();
            }
            long stop = System.currentTimeMillis();
            return stop - start;
        }
    
    }
    

    Output:

    throwCatchTime = 19
    newExceptionTime = 77
    newObjectTime = 3
    noStackExceptionTime = 15
    

    This implies that creating a NoStackException is approximately as expensive as repeatedly throwing the same Exception. It also shows that creating an Exception and filling its stack trace takes approximately 4x longer.

提交回复
热议问题