在激活服务器JIT时,什么可能导致我的代码运行速度变慢?

Dur*_*dal 4 java performance jit jvm-hotspot

我正在对MPEG解码器进行一些优化.为了确保我的优化没有破坏任何东西,我有一个测试套件,对整个代码库(优化和原始代码库)进行基准测试,并验证它们是否产生相同的结果(基本上只是通过解码器和crc32提供几个不同的流)输出).

在Sun 1.6.0_18中使用"-server"选项时,测试套件在预热后的优化版本上运行速度降低约12%(与默认的"-client"设置相比),而原始代码库获得了良好的提升运行速度是客户端模式的两倍.

虽然起初这对我来说似乎只是一个热身问题,但我添加了一个循环来多次重复整个测试套件.然后,对于从测试的第3次迭代开始的每次传递,执行时间变为常量,优化版本仍然比客户端模式慢12%.

我也很确定它不是垃圾收集问题,因为代码在启动后绝对没有对象分配.代码主要包括一些位操作操作(流解码)和大量基本浮动数学(生成PCM音频).涉及的唯一JDK类是ByteArrayInputStream(将流提供给测试并从测试中排除磁盘IO)和CRC32(以验证结果).我也观察到与Sun JDK 1.7.0_b98相同的行为(只有15%而不是12%).哦,测试都是在同一台机器(单核)上完成的,没有运行其他应用程序(WinXP).虽然测量的执行时间存在一些不可避免的变化(使用System.nanoTime btw),但使用相同设置的不同测试运行之间的差异从未超过2%,通常低于1%(预热后),

是否有任何已知的编码模式在服务器JIT上表现更差?如果做不到这一点,有什么选择可以"偷看"引擎盖并观察JIT在那里做什么?

  • 也许我误解了我的"热身"描述.没有明确的预热代码.整个测试套件(包括12个不同的MPEG流,包含〜180K音频帧总)被执行10次,我认为该第一3个运行为"预热".在我的机器上进行一轮测试需要大约40秒的100%cpu.

  • 我按照建议玩了JVM选项并使用"-Xms512m -Xmx512m -Xss128k -server -XX:CompileThreshold = 1 -XX:+ PrintCompilation -XX:+ AggressiveOpts -XX:+ PrintGC"我可以验证所有编译都发生在前3轮.垃圾收集每3-4轮踢一次,最多耗时40ms(512m非常超大,因为测试可以用16米就好了).由此我得出结论,垃圾收集在这里没有影响.不过,比较客户端与服务器(其他选项未改变)仍有12/15%的差异.

mdm*_*dma 6

正如您所见,JIT可能会扭曲测试结果,因为它在后台线程中运行,从运行测试的主线程中窃取cpu周期.

除了偷窃周期,它也是asynchornos,因此当你完成预热并开始真正的测试时,你无法确定它是否完成了它的工作.要强制进行同步JIT编译,可以使用-XBatch非标准选项强制JIT编译到前台线程,这样您就可以确保在预热完成时JIT已完成.

HotSpot不会立即编译方法,而是等待方法执行了一定次数.在-XX选项的页面上,它指出-server的默认值是10000次,而-client的默认值是1500次.这可能是导致速度减慢的原因,特别是如果你的热身最终调用了1500到10000次之间的许多关键方法:使用-client选项它们将在预热阶段进行JIT,但是使用-server运行,编译可能会延迟执行你的配置代码.

您可以在HotSpot通过设置编译方法之前更改所需的方法调用次数-XX:CompileThreshold.我选择二十,所以即使在测试运行几次之后,即使是模糊的热点(冷热点?)也会在预热期间被转换.这在过去对我有用,但YMMV和不同的值可能会给你更好的结果.

您还可以检查HotSpot VM Options页面以查找-client和-server选项之间不同的其他选项,尤其是垃圾收集器选项,因为它们有很大不同.

看到