写在前面

本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和文献引用请见100个问题搞定Java虚拟机

解答

profiling 是指在程序执行过程中,收集能够反映程序执行状态的数据。

这里所收集的数据我们称之为程序的 profile。

这些 profiler 大多通过注入(instrumentation)或者 JVMTI 事件来实现的。

补充

profiling 的触发时机

通常情况下,解释执行过程中仅收集方法的调用次数以及循环回边的执行次数。

当方法被 3 层 C1 所编译时,生成的 C1 代码将收集条件跳转指令的分支 profile,以及类型相关指令的类型 profile。

在部分极端情况下,Java 虚拟机也会在解释执行过程中收集这些 profile。

基于分支 profile 的优化以及基于类型 profile 的优化都将对程序今后的执行作出假设。

这些假设将精简所要编译的代码的控制流以及数据流。在假设失败的情况下,Java 虚拟机将采取去优化,退回至解释执行并重新收集相关的 profile。

这些耗费巨大代价收集而来的 profile 具体有什么作用?

C2 可以根据收集得到的数据进行猜测,假设接下来的执行同样会按照所收集的 profile 进行,从而作出比较激进的优化。

基于分支 profile 的优化

根据条件跳转指令的分支 profile,即时编译器可以将从未执行过的分支剪掉,以避免编译这些很有可能不会用到的代码,从而节省编译时间以及部署代码所要消耗的内存空间。

此外,“剪枝”将精简程序的数据流,从而触发更多的优化。在现实中,分支 profile 出现仅跳转或者仅不跳转的情况并不多见。

当然,即时编译器对分支 profile 的利用也不仅限于“剪枝”。它还会根据分支 profile,计算每一条程序执行路径的概率,以便某些编译器优化优先处理概率较高的路径。

基于类型 profile 的优化

和基于分支 profile 的优化一样,基于类型 profile 的优化同样也是作出假设,从而精简控制流以及数据流。

这两者的核心都是假设。

对于分支 profile,即时编译器假设的是仅执行某一分支;对于类型 profile,即时编译器假设的是对象的动态类型仅为类型 profile 中的那几个。

上一篇 下一篇