为什么调用顺序会影响执行时间?

时间:2018-11-14 03:34:30

标签: java performance method-reference

上下文

因此,我通过向其添加一些方法引用来处理与How slow are Java exceptions?相关的代码。修改后的代码如下

/**
 * [https://stackoverflow.com/questions/299068/how-slow-are-java-exceptions]
 * 
 * The original code is credited to 
 * [https://stackoverflow.com/users/15809/mecki] &
 * [https://stackoverflow.com/users/581994/hot-licks]
 * 
 */
public class ThrowableCost {
    int value;

    public int getValue() {
        return value;
    }

    public void reset() {
        value = 0;
    }

    // This one will regularly throw one
    public void method3(int i) {
        value = ((value + i) / i) << 1;
        // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
        // an AND operation between two integers. The size of the number plays
        // no role. AND on 32 BIT always ANDs all 32 bits
        if ((i & 0x1) == 1) {
            throw new RuntimeException();
        }
    }

    // Similar to {@link #method3} but not throw the newly created exceptions.
    public void method5(int i) {
        value = ((value + i) / i) << 1;
        // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
        // an AND operation between two integers. The size of the number plays
        // no role. AND on 32 BIT always ANDs all 32 bits
        if ((i & 0x1) == 1) {
            new RuntimeException();
        }
    }

    private RuntimeException e = new RuntimeException();

    // Similar to {@link #method3} but throw the pre-created exception.
    public void method6(int i) {
        value = ((value + i) / i) << 1;
        // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
        // an AND operation between two integers. The size of the number plays
        // no role. AND on 32 BIT always ANDs all 32 bits
        if ((i & 0x1) == 1) {
            throw e;
        }
    }

    public static void main(String[] args) {
        System.out.println("Running...");
        ThrowableCost t = new ThrowableCost();

        invokeWithTryCatch(t, t::method3, "method3");
        invokeWithTryCatch(t, t::method5, "method5");
        invokeWithTryCatch(t, t::method6, "method6");

        System.out.println("Done!");
    }

    private static void invokeWithTryCatch(ThrowableCost t, Consumer c, String label) {
        long l = System.currentTimeMillis();
        int i;
        t.reset();
        for (i = 1; i < 100000000; i++) {
            try {
                c.accept(i);
            } catch (Exception e) {
                // Do nothing here, as we will get here
            }
        }
        l = System.currentTimeMillis() - l;
        System.out.println(String.format("%s took %d ms, result was %d", label, l, t.getValue()));
    }

}

/**
 * Similar to {@link java.util.function.Consumer} but avoid auto-boxing in our case.
 */
interface Consumer{
    void accept(int i);
}

输出为

Running...
method3 took 30088 ms, result was 2
method5 took 29948 ms, result was 2
method6 took 6298 ms, result was 2
Done!

您可以看到method6的执行时间约为6000毫秒。

但是,如果我

  • 单独调用method6(通过注释掉其他invokeWithTryCatch)或
  • 首先(通过交换method6的顺序调用invokeWithTryCatch
  • 通过实例method6而不是t内部的c调用了invokeWithTryCatch

然后method6的执行要短得多(即:大约700毫秒)

问题 为什么用这种方法invokeWithTryCatch的顺序会影响method6的执行时间?

注意 我尝试过同时使用JDK8和JDK11。

0 个答案:

没有答案