简体   繁体   English

Java中new运算符与newInstance()的性能

[英]Performance of new operator versus newInstance() in Java

I was using newInstance() in a sort-of performance-critical area of my code. 我在代码的newInstance()性能至关重要的区域中使用了newInstance() The method signature is: 方法签名为:

<T extends SomethingElse> T create(Class<T> clasz)

I pass Something.class as argument, I get an instance of SomethingElse , created with newInstance() . 我将Something.class作为参数传递,我获得了SomethingElse的实例,该实例是使用newInstance()创建的。

Today I got back to clear this performance TODO from the list, so I ran a couple of tests of new operator versus newInstance() . 今天,我从列表中清除了此性能TODO,因此我对new运算符和newInstance()进行了一些测试。 I was very surprised with the performance penalty of newInstance() . 我对newInstance()的性能损失感到非常惊讶。

I wrote a little about it, here: http://biasedbit.com/new-vs-newinstance/ 我在这里写了一些有关它的信息: http : //biasedbit.com/new-vs-newinstance/

(Sorry about the self promotion... I'd place the text here, but this question would grow out of proportions.) (对不起自我提升。我将文本放在这里,但是这个问题会超出比例。)

What I'd love to know is why does the -server flag provide such a performance boost when the number of objects being created grows largely and not for "low" values, say, 100 or 1000. 我很想知道的是,当创建的对象数量大大增加而不是针对“低”值(例如100或1000)时, -server标志为什么能提供这样的性能提升。

I did learn my lesson with the whole reflections thing, this is just curiosity about the optimisations the JVM performs in runtime, especially with the -server flag. 我确实从全反射的东西中学到了教训,这只是对JVM在运行时执行的优化的好奇心,特别是使用-server标志时。 Also, if I'm doing something wrong in the test, I'd appreciate your feedback! 另外,如果我在测试中做错了事,也感谢您的反馈!


Edit: I've added a warmup phase and the results are now more stable. 编辑:我已经添加了一个预热阶段,结果现在更加稳定。 Thanks for the input! 感谢您的输入!

I did learn my lesson with the whole reflections thing, this is just curiosity about the optimisations the JVM performs in runtime, especially with the -server flag. 我确实从全反射的东西中学到了教训,这只是对JVM在运行时执行的优化的好奇心,特别是使用-server标志时。 Also, if I'm doing something wrong in the test, I'd appreciate your feedback! 另外,如果我在测试中做错了事,也感谢您的反馈!

Answering the second part first, your code seems to be making the classic mistake for Java micro-benchmarks and not "warming up" the JVM before making your measurements. 首先回答第二部分,您的代码似乎是Java微基准测试的典型错误,而不是在进行测量之前“预热” JVM。 Your application needs to run the method that does the test a few times, ignoring the first few iterations ... at least until the numbers stabilize. 您的应用程序需要运行进行测试的方法几次,而忽略前几次迭代……至少要等到数字稳定下来为止。 The reason for this is that a JVM has to do a lot of work to get an application started; 原因是JVM必须做很多工作才能启动应用程序。 eg loading classes and (when they've run a few times) JIT compiling the methods where significant application time is being spent. 例如,加载类和(在它们运行了几次之后)JIT会在花费大量应用程序时间的情况下编译方法。

I think the reason that "-server" is making a difference is that (among other things) it changes the rules that determine when to JIT compile. 我认为“服务器”之所以有所作为,是因为(除其他事项外)它更改了决定何时进行JIT编译的规则。 The assumption is that for a "server" it is better to JIT sooner this gives slower startup but better throughput. 假设对于“服务器”来说,最好是JIT越早越好,这会导致启动速度较慢,但​​吞吐量更高。 (By contrast a "client" is tuned to defer JIT compiling so that the user gets a working GUI sooner.) (通过对比,“客户端”被调整为延迟JIT编译,以便用户可以更快地获得工作的GUI。)

Among other things, the garbage collection profile for the -server option has significantly different survivor space sizing defaults. 除其他事项外, -server选项的垃圾收集配置文件具有明显不同的生存者空间大小缺省值。

On closer reading, I see that your example is a micro-benchmark and the results may be counter-intuitive. 通过仔细阅读,我发现您的示例是一个微基准测试 ,其结果可能与直觉相反。 For example, on my platform, repeated calls to newInstance() are effectively optimized away during repeated runs, making newInstance() appear 12.5 times faster than new . 例如,在我的平台上,在重复运行期间有效地优化了对newInstance()重复调用,使newInstance()显示速度比new快12.5倍。

IMHO the performance penalty comes from the class loading mechanism. 恕我直言,性能损失来自类加载机制。 In case of reflection all the security mechanism are used and thus the creation penalty is higher. 在反思的情况下,将使用所有安全机制,因此创建代价更高。 In case of new operator the classes are already loaded in VM (checked and prepared by the default classloader) and the actual instantiation is a cheap process. 在使用新操作符的情况下,这些类已经被加载到VM中(由默认的类加载器检查和准备),并且实际的实例化是一个廉价的过程。 The -server parameter does a lot of JIT optimizations for the frequently used code. -server参数对常用代码进行了许多JIT优化。 You might want to try it also with -batch parameter that will trade off the startup-time but then the code will run faster. 您可能还希望使用-batch参数尝试一下,该参数将权衡启动时间,但代码运行速度会更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM