晚期(运行期)优化
1.为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time,JIT编译器)。
2.Hotspot虚拟机内的即时编译器
(1)解释器与编译器
主流的商用虚拟机,如Hotspot,J9等,都同时包含解释器和编译器。
解释器与编译器两者各有优势:当程序需要快速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间得推移,编译器组件发挥作用,把越来越多的代码编译成本地代码,可以获取更高的执行效率。
Hotspot虚拟机中内置了两个编译器,分别称为Client Compiler和Server Compiler,简称C1编译器和C2编译器,也叫Opto编译器。
目前主流的Hotspot虚拟机中,默认采用解释器与其中一个编译器直接配合的方式工作。用户可以只用“-client”或“-server”参数去强制指定虚拟机运行在Client模式或Server模式。
可以使用参数“-Xint”强制虚拟机运行于“解释模式”。
可以使用参数“-Xcomp”强制虚拟机运行于“编译模式”。
分层编译:
a) 第0层:程序解释执行,解释器不启动性能监控功能,可以触发第1层 编译
b) 第1层:也称为C1编译,将字节码编译为本地代码,进行简单,可靠的优化,如有必要将加入性能监控的逻辑
c) 第2层(或2层以上):也称为C2编译,也是将字节码编译成本地代码,但是会启用一些编译耗时较低的优化,甚至会根据性能监控信息进行一些不可靠的激进优化
(2)编译对象与触发条件
热点探测判定方式:基于采样的热点探测和计数的热点探测。
Hotspot虚拟机采用基于计数器的热点探测方法,它为每个方法准备了两类计数器:方法调用计数器和回收计数器。
(3)编译过程
Client Compiler是一个简单快速地三段编译器,主要的关注点在于局部性的优化,而放弃了许多耗时较长的局部优化手段。
第一阶段,一个平*立的前端将字节构造成一种高级中间代码表示(HIR)
第二阶段,一个平台相关的后端从HIR中产生低级中间代码表示(LIR)
最后阶段,在平台相关的后端使用线性扫描算法在LIR上分配寄存器,并在LIR上做窥孔优化,然后产生机器代码
Server Compiler是专门面向服务端的典型用用并为服务端的性能配置特别调整过的编译器,也是一个充分优化过的高级编译器,它会执行所有经典的优化动作。
编译优化技术
1.优化技术
- 编译器策略:延迟编译,分层编译,栈上替换,延迟优化,程序依赖图表示,静态单赋值表示。
- 基于性能监控的优化技术:乐观空值断言,乐观类型断言,乐观类型增强,乐观数组增强,裁剪未被选择的分支,乐观的多态内联。分支频率预测,调用频率预测
- 基于证据的优化技术:精确性推断,内存值推断,内存值跟踪,常量折叠,重组,操作符退化,空值检查消除。类型检测退化,类型检测消除,代数化简,公共子表达式消除
- 数据流敏感重写:条件常量传播,基于六承载的类型缩减转换,无用代码消除
- 语言相关的优化技术:类型继承关系分析,去虚拟机化,符号常量传播,自动装箱,消除逃逸分析,锁消除,锁膨胀,消除反射
- 内存及代码位置交换:表达式提升,表达式下沉,冗余存储消除,相邻存储合并,交汇点分离
- 循环变换:循环展开,循环剥离,安全点消除,迭代分离,范围检查消除
- 局部代码调整:内联,全局代码提升,基于热度的代码分离,Switch调整
- 控制流图变换:本地代码编排,本独代码封包,延迟槽填充,着色图寄存器分配,线性扫描寄存器分配,复写聚合,常量分裂,复写移除,地址模式匹配。指令窥孔优化,基于确定有限状态机的代码生成
2.公共子表达式
优化仅限于程序的基本快内,便称为内部公共子表达式消除。
如果优化的范围涵盖了多个基本块,就称为全局公共子表达式消除。