《深入理解JVM虚拟机》 - 运行期优化

javac生成字节码,字节码可以解释执行,也可以进一步通过JIT编译执行,JIT把字节码变为机器码。

JVM采用解释器interpreter与JIT编译器compiler并存的架构:二者相互配合;当程序需要迅速启动和执行的时候,解释器首先发挥作用,省去编译的时间,立即执行。程序运行后,编译器逐渐把高频调用代码(热点代码)用JIT编译为本地代码(平台相关机器码),并进行优化,以获取更高的执行效率。JIT可以采用激进的优化方式,如果不成立可以回退到解释器执行。

HotSpot内置了两个JIT编译器:Client/Server Compiler;默认采用解释器和其中一个编译器直接配合的方式,虚拟机根据版本和宿主机器的硬件性能自动选择运行模式,进而根据运行模式决定使用哪个编译器。用户也可以用-client/server参数强制设定虚拟机的运行模式。另外,可以通过参数指定混合/解释/编译模式。-Xint:强制虚拟机运行于解释模式;-Xcomp:强制虚拟机运行于编译模式

一、JIT分层编译

client/server编译器同时工作,C1/client编译获取更高的编译速度,C2/server获取更好的编译质量。解决的问题:JIT编译为本地代码进行优化都需要占用运行时时间,程序启动响应时间和运行效率需要平衡

第0层:解释执行,解释器不开启性能监控,可触发第1层;第1层:C1编译,将字节码编译为本地代码,简单可靠优化,可加入性能监控逻辑;第2层:C2编译,启动耗时长的优化,根据性能监控信息进行激进优化。

二、JIT编译对象与触发条件 - 热点代码

热点代码包含多次调用的方法和多次执行的循环体OSR(栈上替换),方法帧还在栈上就被替换了。

热点探测用于判断代码是不是热点代码。

1. 基于采样的热点探测:虚拟机周期性的检查各个线程的栈顶,如果发现某个方法经常出现在栈顶,那就是热点方法。

2. 基于计数器的热点探测:为每个方法建立计数器,当调用次数超过阈值就认为是热点代码;HotSpot为每个方法设备两类计数器:

1)方法调用计数器:client模式默认阈值1500;server模式10000;可通过CompileThreshold参数配置。方法被调用时,先检查该方法有没有JIT编译过的版本,有则执行本地代码;没有则将方法的调用计数器加1,判断阈值,超过阈值则向JIT提交编译请求。执行引擎不会同步等待编译请求完成,而是继续进入解释器解释执行;JIT编译完成后,方法的调用入口地址自动改写成新的。BackgroundCompilation用于配置禁止后台编译,执行线程提交编译请求后保持等待。

热度衰减:采用半衰周期内调用次数,而非绝对次数;超过半衰周期后调用次数仍未达到阈值,调用计数器减半。UseCounterDecay配置关闭热度衰减,让计数器统计绝对值;CounterHalfLifeTime配置半衰周期;

2)回边计数器:统计方法中循环体的执行次数;回边表示字节码中遇到的控制流向后跳转的指令。阈值:根据方法调用计数器阈值/OSR比率/解释器监控比率(server模式)计算得出;统计绝对次数。OnStackReplacePercentage配置OSR比率;InterpreterProfilePercentage配置解释器监控比率

三、JIT编译过程

1. Client编译

简单快速的三段式编译器,关注点在局部优化,放弃耗时长的全局优化。

1. 平台独立的前端把字节码构造为高级中间代码HIR,基础优化如方法内联/常量传播;

2. 平台相关的后端把HIR转化为低级中间代码LIR,优化如空值检查消除/范围检查消除;

3. 平台相关的后端把LIR转化为机器代码,使用线性扫描算法分配寄存器,窥孔优化;

2. Server编译

高级优化如无用代码消除,循环展开,循环表达式外提,消除公共子表达式,常量传播,基本块重排序,范围检查消除,空值检查消除。根据解释器/client编译器提供的性能监控信息,进行激进优化,如守护内联,分支频率预测。

四、编译优化技术

程序员的共识:编译执行比解释执行快,因为虚拟机几乎所有优化都在JIT的设计中。

1)方法内联:重要性高于其他优化措施,通常放在优化序列靠前的位置;内联可以去掉方法调用的成本(如建立帧),同时方法内联膨胀便于在更大范围上采取后续优化手段。难点在于java方法大多是虚方法,运行时才知道方法接受者,属于激进优化;内联缓存:在未发生方法调用前,内联缓存为空,第一次调用后,记录方法接受者的版本信息,如果后续方法接受者一致,那就使用该内联。

2)冗余访问消除:y=b.value; z=b.value,替换为z=y;

3)复写传播:y=b.value; z=b.value;z变量没有存在的必要,可以用y变量替换

4)公共子表达式消除:如果一个表达式E已经计算过了,并且所有变量值没有变化,那么E就是公共表达式,直接用之前的计算结果替换E。根据应用范围分为局部/全局。

5)数组边界检查消除:java数组访问array[i]有自动的上下界限访问检查,这种检查降低了编码出错的概率,但也有开销,优化方式比如在循环中进行数组访问,只要循环的终点最大值没有越界,那么前面数组节点的访问可以不做检查。

6)逃逸分析:分析对象动态作用域,当对象在方法中被定义,他可能通过参数传递方式被其他方法引用,称为方法逃逸,甚至可能通过赋值给类变量而被其他线程引用,称为线程逃逸。如果能证明对象不会逃逸,那么可以进行高效优化。

7)栈上分配内存:对象放在栈帧而不是堆,对象内存随着出栈销毁,减轻GC压力

8)同步消除:如果对象不被线程共享则消除耗时的同步措施

9)标量替换:标量指无法再分解的数据,如java原始类型;与之相对的是聚合量,如java对象。标量替换指:把java对象拆散,根据程序访问情况,将用到的成员变量作为原始类型访问。可以省去创建对象的开销,把对象的成员变量存在栈上,而栈上的数据通常会被存储到寄存器。

五、Java编译器 vs c/c++编译器

总体而言,java用运行效率的劣势换取开发效率的优势。JIT占用运行时时间,限制了大规模优化技术的引入;Java类型检查提高安全性的同时,也是耗时的操作;Java中大量使用虚方法,导致内联难度加大;Java由虚拟机而不是程序员负责GC,效率上也有牺牲。

JIT编译器配置:

PrintCompilation:打印被即时编译的方法名称,带%的是OSR触发;

PrintInlining:输出方法内联信息

PrintAssembly:打印生成字节码的反汇编结果(汇编代码)

PrintOptoAssembly / PrintLIR:输出中间代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351