17 | 即时编译(下)
该思维导图由 AI 生成,仅供参考
Profiling
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了Java虚拟机中的即时编译(JIT)技术以及其在profiling和基于分支profile的优化方面的应用。在JIT编译中,0层、2层和3层都会进行profiling,收集方法的调用次数和循环回边的执行次数等数据,用于触发即时编译。文章指出,分支profile和类型profile的收集会带来性能开销,但对于C2编译器进行优化至关重要。基于分支profile的优化可以剪掉从未执行过的分支,节省编译时间和内存空间,并触发更多的优化。此外,即时编译器还会根据分支profile计算程序执行路径的概率,以便优先处理概率较高的路径。文章还介绍了基于类型profile的优化和去优化的过程。总的来说,本文深入解析了Java虚拟机的profiling以及基于所收集的数据的优化和去优化过程,对于提高Java应用程序的性能具有重要意义。
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
全部留言(16)
- 最新
- 精选
- 钱这节是即时编译器的有关优化、去优化、以及何时优化和为什么去优化的内容。可能比较底层,看不见摸不着,一句两句也说不清楚,所以,有点晦涩。 不过经过反复看有点感觉了,小结如下: 1:profile-是收集运行时状态信息,用于编译器优化,当然,收集信息也是耗性能的,所以,也是有前提条件的,当存在优化的可能性时才去费劲吧啦的收集相关信息 2:本节介绍的两种优化的方式思路,都是采用取巧少做事情的方式实现,是建立在假设有些事情不需要做的前提下采用的优化措施 3:如果假设失败,那就去优化呗!还用原来的方式老老实实的解释执行就完了 上述思路是理解了,不过具体实现还是蒙蒙的,应该是水平有限理解不到位吧!整体还是有收获的,所以,非常感谢!
作者回复: 我觉得总结得很到位了。 这篇文章主要就是在介绍profile-guided optimization。介绍了两个优化的案例,以及过于乐观的优化出错时怎么补救。
2018-09-0232 - xiaobang想问下生成的机器码如何和其它未编译的字节码交互?比如相互调用,访问对象内的字段,new对象和对应的gc
作者回复: 在同一方法内,所有的字节码都被编译了。机器码与字节码的切换在方法调用(或者循环回边,对应OSR编译)。 对于已经在堆上的对象,字节码和机器码所使用对象布局是一致的,解释执行器从哪个偏移量访问某字段,机器码也会从这个偏移量访问字段。(对于标量替换的新建对象,机器码会在去优化时重建对象。) JVM里的Runtime是共享的,因此像new对象,实际上都会走到同一个底层方法中。GC是独立的组件,跟字节码机器码没关系,所有new对象都会被JVM runtime追踪。
2018-10-1028 - 徐志毅雨迪老师,请问有什么方式可以跟踪JMM里主内存与工作内存的交互,如什么时候加载到工作内存、什么时候同步到主内存~ 盼回复,谢谢
作者回复: JMM的工作内存是个虚拟概念,映射到我们的体系架构就是CPU缓存。 要追踪缓存更新事件的话,估计得看perf,VTune等支持CPU performance counter的工具啦
2018-08-2925 - 乔毅请教下老师,JIT利用SIMD进行优化的实现程度?实践中看到大多是仅仅做了循环展开。换言之,有没有什么最佳实践,可以写出JIT SIMD优化友好的代码。
作者回复: 马上会专门开一篇介绍。可以关注一下OpenJDK的Panama项目,会提供vector API
2018-09-031 - 李二木感觉好难,我想问下在现实情况下通过编译器调优的情况多吗?
作者回复: 调优的情况不多的,能做的即时编译器都帮你做了
2018-08-301 - 茶底大佬我已经把graal拿到手了。目前用了下gu下语言挺好使的。但是这个怎么编译啊。。。
作者回复: Java 10自带Graal编译器。Oracle OTN下的GraalVM也是编译好的版本,无需另外编译。 如果想要改Graal源代码后编译,可以参考github.com/oracle/graal/tree/master/compiler/README.md
2018-08-30 - 西门吹牛这篇文章讲的分支优化,类型优化,其实就是对应了CPU指令执行时候的分支预测和冒险技术,JVM只是个虚拟机,都是在模拟整个计算机的运行过程,所以抽象出了内存模型等概率,因为java 在解释执行的时候,效率不高,但是解释执行的好处就是应用程序的启动不需要加载很多类,启动快。 为了平衡解释执行的效率问题,引入即时编译技术,即时编译是把一整块代码(可以是一个方法也可以是一个循环块)直接编译成一段机器码,以便后续热点代码重复使用。 CPU在执行指令的时候,从硬件方面考虑,CPU很快,CPU完全不会等某个条件判断结果出来以后在根据判断结果确定执行那条指令,而是根据预测的方法,不等判断结果就根据判断执行后续的指令,如果对了,就省去等待时间,虽然CPU等待一条指令执行完毕的时间很短,但是这个时间跟cpu的频率一比,还是很可观的,如果预测错了,那就把执行错误的指令移除,涉及到加载到寄存器的数据都删掉,然后在按正确的分支去执行。 java在即时编译的过程中,编译出来的是一整段机器码,程序还没运行呢,无法判断走哪个分支,所以是通过收集的profile 数据进行预测,预测对了当然好,错就错了,在回去走一遍就好,但是根据profile 的数据进行预测,错误的概率不高,试想一下,if条件判断,预测错误的概率是百分之五十,通过收集数据的分析,完全可以把这个错误的概率降到很低,所以jvm在即时编译的时候,完全有必要进行预测,虽然收集数据有开销,但是同样带来的性能效率也有提升。 之前只是对cpu的分支预测和数据冒险有了解,今天看了老师的文章,真是大赞。方法论都是通用的,只是在不同的地方用了不同的实现。2020-07-1524
- 任鑫《老子》尝言:”将欲取之,必先予之“。我们想要使用编译优化来提高代码的执行效率,这就是你想要”取“,然而优化是要付出代价的,这就是”予“;全部都编译优化当然代价太大,我们希望让这个代价小一点,因此需要在前期代码执行过程中收集它的profile,根据这个统计消息来决定哪些优化,怎么优化,这就是要确定优化的策略,这又是一个”取“,收集profile会降低代码运行效率,这就是为了确定这个编译优化策略所要付出的代价,这就是第二个”予“。一切优化均需权衡代价,不管你是”时间换空间“、”空间换时间“什么的,就是一个”将欲取之必先与之“。2020-05-272
- 随心而至这两节都是讲JVM想做一些假设,来提高程序的运行效率(优化);如果假设错了就重新来过(去优化,退化为解释执行)。 这里JVM尝试做的事情,感觉和底层CPU想做的分支预测如出一辙。 具体可参考:https://time.geekbang.org/column/article/1021662019-10-181
- 陈吉米那么有什么规则,可以让代码尽可能被优化?2018-08-2911