如何合理地确定代码块是否已被JIT编译?

Boh*_*ian 10 java testing jit bytecode performance-testing

在进行java代码的性能测试时,您需要测试JIT编译的代码,而不是原始的字节码.要使字节码被编译,必须通过多次执行代码来触发编译,并且还允许后台线程有足够的产生时间来完成编译.

  • 代码路径的"预热"执行的最小数量是什么,需要"非常自信"代码将被JIT编译?
  • 主线程的最小休眠时间是什么,"非常有信心"编译已经完成(假设代码块很小)?

我正在寻找一个可以安全应用于任何现代操作系统的门槛,比如Mac OS或Windows用于开发环境,Linux用于CI /生产.

Ale*_*lev 13

由于OP的意图实际上并未确定该块是否是JIT编译的,而是确保测量优化的代码,我认为OP需要观察其中一些基准测试.

TL; DR版本:没有可靠的方法来判断你是否达到了"稳定状态":

  • 您只能在很长一段时间内测量球场估计,以确定您的混凝土系统达到某些可以声称"稳定"的状态的正常时间.

  • 观察-XX:+PrintCompilation是不可靠的,因为你可能处于计数器仍然不稳定的阶段,而JIT正在等待编译下一批现在热门的方法.因此,你可以很容易地获得一些热身.该方法甚至可以多次重新编译,具体取决于分层编译器的数量.

  • 虽然有人可能会争论调用阈值,但这些事情也不可靠,因为可能涉及分层编译,方法可能会更快地在调用者中内联,概率计数器可能会错过更新等等.也就是说,常见的智慧-XX:CompileThreshold=#是不可靠的.

  • JIT编译并不是您追求的唯一热身效果.自动GC启发式,调度程序启发式等也需要预热.

获得一个微基准线束,这将使您的任务更容易!


Raf*_*ter 6

首先,对于在客户端或服务器模式下运行的JVM,结果很可能会有所不同.其次,这个数字在很大程度上取决于代码的复杂性,我担心你将不得不为每个测试用例进行探索性估计.通常,字节代码越复杂,可以对其应用的优化越多,因此为了使JVM深入到其工具箱中,您的代码必须相对更热.JVM可能会重新编译一段代码十几次.

此外,"真实世界"编译取决于运行字节代码的上下文.例如,当单态调用站点被提升为变形站点时,可能发生编译,使得观察到的编译实际上表示去优化.因此,在假设您的微型标记反映代码的实际性能时要小心.

而不是建议的标志,我建议您使用CompilationMXBean它来检查JVM在编译时仍然花费的时间.如果时间太长,请重新运行测试,直到值稳定足够长.(请耐心等待!)框架可以帮助您创建良好的基准.就个人而言,我喜欢卡尺.但是,永远不要相信您的基准.

根据我的经验,当您模仿javac的习语时,自定义字节代码表现最佳.提到我可以告诉的一个轶事,我曾经为Java源代码编写了自定义字节代码,相当于:

int[] array = {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)

javac创建数组并dup用于分配每个值但我将数组引用存储在局部变量中并将其加载回操作数堆栈以分配每个值.阵列的大小比那个大,并且有一个值得注意的性能差异.

最后,我在编写基准之前推荐这篇文章.


pru*_*nge 4

不确定数字,但在进行速度测试时我所做的是:

  • 带着旗帜奔跑-XX:-PrintCompilation
  • 预热 JVM,直到不再生成编译调试消息,并且如果可能的话,计时变得一致