【问题标题】:What can cause my code to run slower when the server JIT is activated?激活服务器 JIT 后,什么会导致我的代码运行缓慢?
【发布时间】:2023-08-04 11:43:01
【问题描述】:

我正在对 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 非常大,因为测试可以用 16m 运行就好了)。由此我得出结论,垃圾收集在这里没有影响。尽管如此,将客户端与服务器进行比较(其他选项不变)仍然存在 12/15% 的差异。

【问题讨论】:

    标签: java performance jit jvm-hotspot


    【解决方案1】:

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

    除了偷循环,它也是异步的,所以当你完成热身并开始真正的测试时,你不能确定它已经完成了它的工作。要强制同步 JIT 编译,您可以使用 -XBatch 非标准选项将 JIT 编译强制到前台线程,这样您就可以确保在预热完成时 JIT 已经完成。

    HotSpot 不会立即编译方法,而是等待方法执行一定次数。在 -XX 选项的 page 上,它声明 -server 的默认值为 10000 次,而 -client 的默认值为 1500 次。这可能是导致 减速,特别是如果您的热身最终调用了 1500 到 10000 次之间的许多关键方法:使用-client 选项,它们将在热身阶段被 JITed,但使用 -server 运行,编译可能会延迟执行您的分析代码。

    您可以通过设置 -XX:CompileThreshold 来更改 HotSpot 编译方法之前所需的方法调用次数。我选择了 20,以便在热身过程中即使只运行几次测试,也能转换模糊的热点(微温点?)。这在过去对我有用,但 YMMV 和不同的值可能会给你更好的结果。

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

    【讨论】:

    • 好吧,既然我问过什么可能会影响性能,这是一个合理的答案,所以我会接受。我仍然很确定所描述的预热/gc 问题不是导致我的具体测量的原因。任何进一步的提示仍将不胜感激。
    • 您说原始版本使用 -server 的运行速度是使用 -client 的两倍,但使用 -server 的优化代码比使用 -client 的速度慢 12%。除非您具体详细说明您已应用的优化,否则我无法给您太多建议。我建议进行分析,看看 -client 和 -server 之间的代码在哪里变慢,然后发布一个列出更改的新问题 - 然后你会希望得到更具体的答案。祝你好运!
    最近更新 更多