新操作符与Java中newInstance()的性能

时间:2010-07-21 00:23:43

标签: java performance reflection instantiation

我在代码的一个性能关键区域使用newInstance()。 方法签名是:

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

我传递Something.class作为参数,我得到SomethingElse的实例,使用newInstance()创建。

今天我从列表中回过头来清除这个性能TODO,所以我运行了几个new运算符与newInstance()的测试。我对newInstance()的性能损失感到非常惊讶。

我写了一点关于它,在这里:http://biasedbit.com/new-vs-newinstance/

(对于自我推销感到抱歉......我会把文字放在这里,但这个问题会不成比例。)

我想知道的是,当创建的对象数量大幅增加而不是“低”值(例如100或1000)时,-server标志为什么会提供这样的性能提升。

我确实从整个思考过程中吸取了教训,这只是对JVM在运行时执行的优化的好奇心,尤其是-server标志。另外,如果我在测试中做错了什么,我会很感激您的反馈!


编辑:我添加了一个预热阶段,结果现在更加稳定。感谢您的投入!

3 个答案:

答案 0 :(得分:5)

  

我确实从整个思考过程中吸取了教训,这只是对JVM在运行时执行的优化的好奇心,特别是对于-server标志。另外,如果我在测试中做错了什么,我会很感激您的反馈!

首先回答第二部分,您的代码似乎是Java微基准测试的经典错误,而不是在进行测量之前“预热”JVM。您的应用程序需要运行几次执行测试的方法,忽略前几次迭代...至少在数字稳定之前。原因是JVM必须做很多工作才能启动应用程序;例如加载类和(当它们运行几次时)JIT编译正在花费大量应用程序时间的方法。

我认为“-server”产生影响的原因是(除其他外)它改变了决定何时进行JIT编译的规则。假设对于“服务器”,JIT越快越好,启动速度越慢,但吞吐量越高。 (相比之下,“客户端”被调整为推迟JIT编译,以便用户更快地获得有效的GUI。)

答案 1 :(得分:1)

除其他外,-server选项的垃圾回收配置文件具有明显不同的survivor space sizing默认值。

仔细阅读后,我发现您的示例是micro-benchmark,结果可能违反直觉。例如,在我的平台上,在重复运行期间,有效优化了对newInstance()的重复调用,使newInstance()的显示速度比new快12.5倍。

答案 2 :(得分:1)

恕我直言,性能损失来自类加载机制。 在反射的情况下,使用所有安全机制,因此创建惩罚更高。 在新运算符的情况下,类已经加载到VM中(由默认类加载器检查和准备),并且实际的实例化是一个廉价的过程。 -server参数对常用代码进行了大量JIT优化。您可能还想使用-batch参数来尝试它,这将在启动时间之间进行权衡,但代码将运行得更快。