晚期(运行期)优化

概述

Java程序最初通过解释器进行解释执行,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为"热点代码",为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(JIT编译器)

  • 为何HotSpot 虚拟机要使用解释器和编译器并存的架构
  • 为何HotSpot 虚拟机要实现两个不同的即时编译器
  • 程序猿何时使用解释器,何时使用编译器执行
  • 哪些程序代码会被编译为本地代码,如何编译为本地代码
  • 如何从外部观察即时编译器的编译过程和编译结果

解释器和编译器

解释器和编译器的优势:
当程序需要迅速启动和执行的时候,解释器可以发挥作用,省去编译的时间,立即执行,在程序运行之后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码,获取更高的执行效率。
当程序运行环境中内存资源限制较大,可以使用解释执行节约内存,反之可以使用编译执行提高效率
同时解释器可以作为编译器激进优化的一个“逃生门”,当激进优化不成立,可以通过逆优化退回解释执行状态继续执行
在这里插入图片描述
Client Compiler 和 Server Compiler
即时编译器编译本地代码需要占用程序运行时间,要编译出优化程度高的代码,所花费的时间更长,而且要编译出优化程度更高的代码,解释器可能要替编译器收集性能监控信息,对解释执行的速度也有影响,为了在程序启动和运行效率之间达到最佳平衡,HotSpot虚拟机会逐渐开启分层编译,分层编译根据编译器编译,优化的规模与耗时,划分出不同的编译层次:

  • 第0层,程序解释执行,解释器不开启性能监控功能,可触发第1层编译
  • 第1层,C1编译,将字节码编译为本地代码,进行简单,可靠的优化,如有必要将加入性能监控逻辑
  • 第2层,C2编译,将字节码编译为本地代码,开启一些编译耗时较长的优化,甚至根据性能监控进行一些不可靠的激进优化
    分层编译开启后,Client Compiler 和 Server Compiler 将会同时工作,许多代码可能被多次编译

编译对象和触发条件

触发对象
热点代码 : 被多次调用的方法 和 被多次调用的循环体
对于方法调用触发的编译,编译器会将整个方法作为编译对象,这种编译也是虚拟机中标准的JIT编译方式,对于循环体,编译器仍然将整个方法作为编译对象,这种编译方式发生在方法执行的过程中,因此称为栈上替换(OSR),即方法栈帧还在栈上,方法就被替换

触发条件
热点检测:探测方法具体被调用了多少次

  • 基于采样的热点探测 周期性检查各个线程的栈顶,发现某个方法经常出现在栈顶,那这个方法就是热点方法
  • 基于计数器的热点探测 虚拟机为每个方法建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值认为它是“热点方法”,需要为每个方法建立并维护计数器,并且不能直接获取方法的调用关系

HotSpot虚拟机使用基于计数器的热点探测的方法,它为每个方法准备两个计数器:方法调用计数器 和 回边计数器,通过确定的阈值触发JIT编译

方法调用计数器
统计方法调用的次数,Client默认阈值为1500次,Server默认为10 000次,当一个方法调用时候,首先检查该方法是否存在被JIT编译过从版本,如果存在,则优先使用编译后的本地代码来执行,如果不存在已经编译过的版本,则将此方法的调用计数器值+1,然后判断方法调用计数器与回边计数器值之和是否超过次方法调用计数器的阈值,如超过阈值,将会向即时编译器提交一个该方法的代码编译请求
在这里插入图片描述
如果不做任何设置,执行引擎并不会同步等待编译器请求完成,而是继续进入解释器按照解释执行方法执行字节码,直到提交的请求被编译器编译完成。
需要注意的是,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数,当超过一定的时间限度,方法调动次数不足时统计次数减半,这个过程叫做方法调用器热度的衰减,

回边计数器
统计一个方法中循环体代码执行次数,在字节码中遇到控制流向后跳转的指令称为“回边”,当解释器遇到一条回边指令时,先检查要执行的代码片段是否存在已经编译好的版本,如果存在,则优先执行编译的代码,否则回边计数器+1,然后判断方法调用器与回边计数器之和是否超过回边计数器的阈值,如超过,则提交一个OSR编译请求,并将回边计数器的值降低一些,以便继续在解释器中执行循环,等待编译器输出编译结果。
与方法计数器不同,回边计数器没有计数热度衰减的过程

编译过程

默认设置下,无论方法调用产生的即时编译请求,还是OSR编译请求,虚拟机代码编译器还未完成之前,都仍然按照解释执行继续执行。
Client Compiler 编译过程
简单快速的三段式,主要关注局部性的优化,放弃了许多耗时的全局优化手段

  • 第一阶段 由一个独立平台的前端将字节码构造成一种高级中间代码表示(HIR),进行如 方法内联,常量传播等优化
  • 第二阶段 由一个平台相关的后端从HIR中产生低级中间代码(LIR),进行空值检查消除,范围检查消除等
  • 第三阶段 由平台相关的后端使用线性扫描算法在LIR分配寄存器
    在这里插入图片描述
    Server Compiler 编译过程
    实现经典的优化动作,无用代码消除,消除公共子表达式,常量传播,并根据解释器或Client Compiler 提供的性能监控信息,进行一些不稳定的激进优化,如守护内联
主要内容:本文详细介绍了一种QRBiLSTM(分位数回归双向长短记忆网络)的时间序列区间预测方法。首先介绍了项目背景以及模型的优势,比如能够有效利用双向的信息,并对未来的趋势上限和下限做出估计。接着从数据生成出发讲述了具体的代码操作过程:数据预处理,搭建模型,进行训练,并最终可视化预测结果与计算分位数回归的边界线。提供的示例代码可以完全运行并且包含了数据生成环节,便于新手快速上手,深入学习。此外还指出了模型未来发展的方向,例如加入额外的输入特性和改善超参数配置等途径提高模型的表现。文中强调了时间序列的标准化和平稳检验,在样本划分阶段需要按时间序列顺序进行划分,并在训练阶段采取合适的手段预防过度拟合发生。 适合人群:对于希望学习和应用双向长短时记忆网络解决时序数据预测的初学者和具有一定基础的研究人员。尤其适用于有金融数据分析需求、需要做多一步或多步预测任务的从业者。 使用场景及目标:应用于金融市场波动预报、天气状况变化预测或是物流管理等多个领域内的决策支持。主要目的在于不仅能够提供精确的数值预计还能描绘出相应的区间概率图以增强结论置信程度。 补充说明:本教程通过一个由正弦信号加白噪构造而成的简单实例来指导大家理解和执行QRBiLSTM流程的所有关键步骤,这既方便于初学者跟踪学习,又有利于专业人士作为现有系统的补充参考工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值