编译原理实战课
宫文学
北京原点代码 CEO
26066 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 55 讲
真实编译器解析篇 (19讲)
编译原理实战课
15
15
1.0x
00:00/00:00
登录|注册

15 | Java JIT编译器(三):探究内联和逃逸分析的算法原理

参考资料
一课一思
课程小结
基于推理的优化(Speculative Optimization)
逃逸分析(Escape Analysis, EA)
内联(Inlining)
Java JIT编译器优化算法

该思维导图由 AI 生成,仅供参考

你好,我是宫文学。
基于 Graal IR 进行的优化处理有很多。但有些优化,针对 Java 语言的特点,会显得更为重要。
今天这一讲,我就带你来认识两个对 Java 来说很重要的优化算法。如果没有这两个优化算法,你的程序执行效率会大大下降。而如果你了解了这两个算法的机理,则有可能写出更方便编译器做优化的程序,从而让你在实际工作中受益。这两个算法,分别是内联和逃逸分析
另外,我还会给你介绍一种 JIT 编译所特有的优化模式:基于推理的优化。这种优化模式会让某些程序比 AOT 编译的性能更高。这个知识点,可能会改变你对 JIT 和 AOT 的认知,因为通常来说,你可能会认为 AOT 生成的机器码速度更快,所以通过这一讲的学习,你也会对“全生命周期优化”的概念有所体会。
好,首先,我们来看看内联优化。

内联(Inlining)

内联优化是 Java JIT 编译器非常重要的一种优化策略。简单地说,内联就是把被调用的方法的方法体,在调用的地方展开。这样做最大的好处,就是省去了函数调用的开销。对于频繁调用的函数,内联优化能大大提高程序的性能。
执行内联优化是有一定条件的。第一,被内联的方法要是热点方法;第二,被内联的方法不能太大,否则编译后的目标代码量就会膨胀得比较厉害。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java JIT编译器的优化算法是提高程序执行效率的关键。本文介绍了内联和逃逸分析两种重要的优化算法。内联优化通过展开被调用方法的方法体,省去函数调用开销,特别适用于频繁调用的短方法,同时还能进行跨过程的优化。逃逸分析则能帮助编译器确定对象的生命周期,从而进行更精确的优化。此外,文章还介绍了基于推理的优化模式,以及多态内联技术。这些优化算法的应用能显著提高程序性能,尤其在JIT编译中,能充分利用运行时信息进行优化,相较于AOT编译更具优势。 逃逸分析是JVM的另一个重要的优化算法,能够让编译器判断对象是否能够在创建它的方法或线程之外访问。根据对象的逃逸情况,可以采用更加优化的方法来管理对象,如栈上分配内存和标量替换。逃逸分析的算法利用连接图来分析程序中对象之间的引用关系,通过部分逃逸分析和基于推理的优化模式,进一步提高优化效果。总之,逃逸分析能够让对象在栈上申请内存,做标量替换,从而大大减少对象处理的开销,对于对象生命周期比较短的场景,优化效果是非常明显的。 基于推理的优化是JIT编译器根据运行时收集的统计信息来做优化的技术。通过实例分析,读者可以直观了解基于推理的优化对程序性能的影响。这种优化方式有时会比基于静态分析的AOT产生出性能更高的目标代码,强调了“全生命周期”优化的概念。熟悉这些重要的优化算法的原理,有助于读者写出性能更高的程序,同时也为胜任编译器的开发工作奠定基础。 总的来说,本文介绍了Java JIT编译器中的重要优化算法,以及基于运行时信息做推理优化的技术。通过深入了解这些算法,读者可以写出更适合编译器优化的程序,从而在实际工作中受益。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《编译原理实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(5)

  • 最新
  • 精选
  • 😐饲养员小张😐
    老师,能讲讲不同语言混编的时候,编译器到底会怎么做么?
最近在做swift和objc的混编的事情,有点没搞明白,如果主工程是objc引入swift文件,和主工程是swift引入objc文件有什么区别么?
还有两种语言是怎么做到识别对方的呢?像编辑器的代码补全和报错都是怎么识别的呢?毕竟这时候还没有真正的编译啊!
感谢老师

    作者回复: 现代的IDE,是内置了编译功能的,这是IDE能那么智能的原因。一般只需要实现前端功能就行了,能够检查语法和语义的错误。 比如,如果你需要让Visual Studio Code支持某种语言,你需要提供一个支持语言服务器协议(LSP)的后台服务,让编辑器调用它的功能来支持解析、即时提示等功能。

    2020-07-07
    2
    5
  • chris
    请教老师图1图2中的黑线和绿线是什么意思

    作者回复: 黑线和绿线都跟内存读写有关。 与内存状态有关的操作所构成的流,有时还会叫做Effect流,效果流。这时候会产生前后序的依赖关系。

    2020-07-08
    2
  • 易昊
    “它的具体做法是,在运行时,编译器会统计在调用多态方法的时候,到底用了哪几个实现。”这个是否有一定程度限制条件,比如我的程序运行在别人的虚拟机上,应该就统计不到了吧?

    作者回复: 这句话我再解释一下。 比如,A有10个子类,B1、B2、B3...B10 但在实际运行时,很多子类可能从来没有用到过,只有B2和B3会被用到。那么,编译器只需要为这两个子类做优化就行了。这就是JIT的优势。它是根据实际运行的情况来优化的。

    2020-07-07
  • lion_fly
    多态内联:Inlining of Virtual Methods。 老师这篇论文的连接失效了
    2021-03-12
    1
  • jack123
    内联的第二个代码 “inlining方法” 打漏了,应该是“inlingingTest方法” 还有在内联优化的第1个部分--加载本地变量 一般我们使用getter和setter是因为想要封装外界直接对成员变量的访问,但是编译器这里直接加载私有字段,打破了private,在编译器层面是怎么做到的呢?或者说private关键词在Java编译器层面是怎么实现的呢,只是通过一个语法糖?还是底层就无法通过对象的offset偏移找到它的成员变量呢?
    2021-10-09
    2
收起评论
显示
设置
留言
5
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部