我在代码的一个性能关键区域使用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
标志。另外,如果我在测试中做错了什么,我会很感激您的反馈!
编辑:我添加了一个预热阶段,结果现在更加稳定。感谢您的投入!
答案 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参数来尝试它,这将在启动时间之间进行权衡,但代码将运行得更快。