【发布时间】:2017-08-04 19:50:16
【问题描述】:
我在这里看到很多线程比较并尝试回答哪个更快:newInstance 或 new operator。
查看源代码,newInstance 似乎应该慢得多,我的意思是它做了很多安全检查并使用反射。我决定测量,首先运行 jdk-8。这是使用jmh的代码。
@BenchmarkMode(value = { Mode.AverageTime, Mode.SingleShotTime })
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@State(Scope.Benchmark)
public class TestNewObject {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder().include(TestNewObject.class.getSimpleName()).build();
new Runner(opt).run();
}
@Fork(1)
@Benchmark
public Something newOperator() {
return new Something();
}
@SuppressWarnings("deprecation")
@Fork(1)
@Benchmark
public Something newInstance() throws InstantiationException, IllegalAccessException {
return Something.class.newInstance();
}
static class Something {
}
}
我不认为这里有什么大的惊喜(JIT 做了很多优化,使得这种差异没有那么大):
Benchmark Mode Cnt Score Error Units
TestNewObject.newInstance avgt 5 7.762 ± 0.745 ns/op
TestNewObject.newOperator avgt 5 4.714 ± 1.480 ns/op
TestNewObject.newInstance ss 5 10666.200 ± 4261.855 ns/op
TestNewObject.newOperator ss 5 1522.800 ± 2558.524 ns/op
热代码的差异将在 2x 左右,单次拍摄时间会更差。
现在我切换到 jdk-9(构建 157 以防万一)并运行相同的代码。 结果:
Benchmark Mode Cnt Score Error Units
TestNewObject.newInstance avgt 5 314.307 ± 55.054 ns/op
TestNewObject.newOperator avgt 5 4.602 ± 1.084 ns/op
TestNewObject.newInstance ss 5 10798.400 ± 5090.458 ns/op
TestNewObject.newOperator ss 5 3269.800 ± 4545.827 ns/op
这是热代码的 50 倍 差异。我正在使用最新的 jmh 版本 (1.19.SNAPSHOT)。
在测试中再添加一种方法后:
@Fork(1)
@Benchmark
public Something newInstanceJDK9() throws Exception {
return Something.class.getDeclaredConstructor().newInstance();
}
这里是 n jdk-9 的总体结果:
TestNewObject.newInstance avgt 5 308.342 ± 107.563 ns/op
TestNewObject.newInstanceJDK9 avgt 5 50.659 ± 7.964 ns/op
TestNewObject.newOperator avgt 5 4.554 ± 0.616 ns/op
谁能解释一下为什么会有这么大的差异?
【问题讨论】:
-
您是否使用带有拼图的 JDK9 构建?
-
这很重要,因为系统模块会有许多额外的访问检查,JIT 可能还不知道如何很好地处理。
-
Class.newInstance()在 Java 9 中已弃用。推荐的替代方案clazz.getDeclaredConstructor().newInstance()的性能会很有趣…… -
@Holger 好点,补充说。差异仍然是 10x,更好,但距离 2x...
-
你能做另一个测试吗,现在在
Something中使用非public(默认访问)构造函数?
标签: java performance java-8 jmh java-9