网站开发需要怎么做/营销传播
在运行过程中会被即时编译的“热点代码”有两类,即:
被多次调用的方法
被多次执行的循环体
对于第一种,编译器会将整个方法作为编译对象,这也是
标准的JIT 编译方式。对于第二种是由循环体出发的,但是编译器依然会以整个方法作为编译对象,因为发生在方法执行过程中,称为
栈上替换。
判断一段代码是否是热点代码,是不是需要出发即时编译,这样的行为称为热点探测(Hot Spot Detection),探测算法有两种,分别为。
基于采样的热点探测(Sample Based Hot Spot Detection):虚拟机会周期的对各个线程栈顶进行检查,如果某些方法经常出现在栈顶,这个方法就是“热点方法”。好处是实现简单、高效,很容易获取方法调用关系。缺点是很难确认方法的reduce,容易受到线程阻塞或其他外因扰乱。
基于计数器的热点探测(Counter Based Hot Spot Detection):为每个方法(甚至是代码块)建立计数器,执行次数超过阈值就认为是“热点方法”。优点是统计结果精确严谨。缺点是实现麻烦,不能直接获取方法的调用关系。
HotSpot 使用的是第二种-基于技术其的热点探测,并且有两类计数器:方法调用计数器(Invocation Counter )和回边计数器(Back Edge Counter )。
这两个计数器都有一个确定的阈值,超过后便会触发 JIT 编译。
首先是方法调用计数器。Client 模式下默认阈值是 1500 次,在 Server 模式下是 10000次,这个阈值可以通过 -XX:CompileThreadhold 来人为设定。如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间之内的方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那么这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减(Counter Decay),而这段时间就成为此方法的统计的半衰周期( Counter Half Life Time)。进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的,可以使用虚拟机参数 -XX:CounterHalfLifeTime 参数设置半衰周期的时间,单位是秒。整个 JIT 编译的交互过程如下图。
第二个回边计数器,作用是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边”( Back Edge )。显然,建立回边计数器统计的目的就是为了触发 OSR 编译。关于这个计数器的阈值, HotSpot 提供了 -XX:BackEdgeThreshold 供用户设置,但是当前的虚拟机实际上使用了 -XX:OnStackReplacePercentage 来简介调整阈值,计算公式如下:
在 Client 模式下, 公式为 方法调用计数器阈值(CompileThreshold)X OSR 比率(OnStackReplacePercentage)/ 100 。其中 OSR 比率默认为 933,那么,回边计数器的阈值为 13995。
在 Server 模式下,公式为 方法调用计数器阈值(Compile Threashold)X (OSR (OnStackReplacePercentage)- 解释器监控比率 (InterpreterProfilePercent))/100
其中 onStackReplacePercentage 默认值为 140,InterpreterProfilePercentage 默认值为 33,如果都取默认值,那么 Server 模式虚拟机回边计数器阈值为 10700 。
执行过程,如下图。