不但能通过profile信息来指导优化,还可以指导不做某些过于激进的优化,减少因过度优化而导致的“去优化”(deoptimization)。 这样也有利于程序快速达到稳定的性能水平,而不必在过度优化—去优化-再优化-再去优化-⋯的震荡多次后才达到稳定。 这与CLR正常执行时的模型其实仍然一致:每个MSIL方法体仍然只有一次被编译的机会;所谓“重新JIT编译“编译的是新的MSIL方法体。 •辅助内嵌决策 – 内嵌经常执行的函数,这样虽然会增加代码长度,但在对性能影响最大的地方却可以得到很好的补偿。 此例中 if (MyConfig.IsDebug) 可以先内联IsDebug属性得知它就是_debug,然后发现它是readonly静态变量,直接用它的值来做优化;假如其值是false,那代码就变成 if ,整个if块就可以被优化消除掉了。
这里单独强调一下,IPO和PGO之间会相互影响,所以同时使用IPO和PGO是个不错的选择,能得到更好的性能。 IPO是静态的分析,PGO是动态的分析,两者结合。 Zing VM基于HotSpot VM开发,与HotSpot VM的执行模式相似,都是解释器+C1+C2的多层混合模式执行引擎,使用了自适应动态编译。 这个过程跟一般的native PGO优化一样,都是要运行多次,依赖training run收集到的profile来引导后续运行的优化。
pgo故障碼: PGO Tigra 故障碼清單
特别是,收集profile通常发生在程序启动阶段,也就是说启动时会比较慢;如果特别在意程序启动的速度的话,这种做法就不合适了。 •辅助矢量化决策 – 对遍历计数高且经常执行的循环进行矢量化处理,这样虽然会增加代码长度,但性能的提高却可以减轻其负面影响。 PGO是Intel编译器的又一优化技术,PGO与其它的一些优化技术/选项有一个明显的区别是:PGO优化是分三步完成的,是一个动态的优化过程。 我们一直致力于提升PHP7的性能, 上个月我们注意到GCC的PGO能在Wordpress上能带来近10%的性能提升, 这个让我们很激动. 然而, PGO正如名字所说(Profile Guided Optimization 有兴趣的可以Google), 他需要用一些用例来获得反馈, 也就是说这个优化是需要和一个特定的场景绑定的.
这个“某种形式”可以称为“baseline execution“,可以由解释器或简单的JIT编译器承担。 “档案导引优化” 编译过程使“英特尔 C++ 编译器”可以更好地利用处理器微体系结构,更有效地使用指令调度与高速缓存,并可以更好地执行分支预测。 通过重新组织代码布局以减少指令缓存反覆、缩减代码长度并减少分支预测失误,它可以帮助提高应用程序性能。
pgo故障碼: 使用Intel编译器( PGO( PGO了解和使用
介绍PGO 即 Profile-guided optimization(归档引导优化),是一种自适应优化手段,不需要对软件代码本身做出改进,即可获得性能的提升,目前已经应用于 GCC、VC++ 等常见的编译器中。 一些开源项目像 Firefox 就默认使用 PGO 编译来优化性能,但是大部分软件上应用率并不高。 的思路是让传统PGO与自适应动态编译结合起来:一个程序可以先跑些training run把细粒度profile信息记录下来,后续执行的时候可以跳过原本收集profile的阶段,直接利用之前记录的profile信息来做优化编译。 这样就减少了程序启动时收集profile的开销,让程序快速达到稳定的高性能状态。
- 另外,以下内容不保证对于所有版本的编译器都正确,编译器的实现也可能有一些变化之处,具体参考官方文档。
- 这是JIT编译的一种特殊做法,虽然没有脱离JIT编译的范畴但增加了一个自由度。
- 这个过程跟一般的native PGO优化一样,都是要运行多次,依赖training run收集到的profile来引导后续运行的优化。
- GPO就是利用运行时反馈的信息来对这些问题进行预测判断,从而提高程序性能。
- 上述步驟將消除故障碼,自行消除可能造成技師無法檢測判定。
- U /Ox:实现最大化的优化,包括自动内联函数的确定,全局优化,使用EBP作为通用寄存器等。
- 说明:本系列文章为个人笔记,如有不正确之处,请参考官方相关文档,如果错误发现,我会尽量更新修改。
- 在正常执行时,每个有MSIL方法体的方法只有一次被编译的机会;一旦被编译过了就雷打不动了。
CLR的执行引擎的模型是“纯编译的单层JIT编译器“。 所有被执行的有MSIL方法体的方法,要么被NGen事先编译成机器码了(PreJIT),要么在方法第一次被调用前进行JIT编译到机器码;总之就是MSIL要编译成机器码之后才被执行。 U /Ox:实现最大化的优化,包括自动内联函数的确定,全局优化,使用EBP作为通用寄存器等。 在IPO部分和上面的部分,都多次提及IPO和PGO以及其他选项之间会相互影响。
GPO就是利用运行时反馈的信息来对这些问题进行预测判断,从而提高程序性能。 举例而言,对于IPO中内联的优化,程序如何知道哪些模块该内联,哪些模块不应该内联(内联会增加代码大小,并不是内联都能优化,其中有一个平衡点),而GPO则能通过程序执行时的反馈信息更加有效的判断是否应该内联。 总体来说,使用PGO能辅助很多其他优化更好的进行,比如更精准的分支预测,提高指令cache的效率,更好的决定函数是否内联,更好的向量化决策(auto-vec),switch语句的优化等等。 从.NET 4.5开始,CLR支持一个新功能叫做ReJIT,用于支持managed profiler通过动态插桩(instrument)来收集性能数据(profile)。 动态插桩意味着修改某个已有方法的MSIL方法体,所以在修改过后需要重新JIT编译才可以执行,因而得名ReJIT。
Azul Systems的Zing VM所实现的ReadyNow! 本文章基于CentOS7系统,Ubuntu安装与此类似。 说明:本系列文章为个人笔记,如有不正确之处,请参考官方相关文档,如果错误发现,我会尽量更新修改。
在这种模式下运行的RyuJIT就可以做到类似本文开头所说的优化——但Visual C++的编译器同样支持PGO,同样可以做这种优化(而且可能做得更好)。 相信未来的.NET Native在逐渐成熟起来之后也会考虑支持PGO。 当前这个Multicore JIT的设计只针对程序启动速度优化,它只观察和记录JIT编译活动,生成的profile粒度太粗,仅是“被JIT编译过的方法的列表“,而不包含任何细粒度的profiling信息(例如说条件分支、虚方法的被调用对象的实际类型等)。 JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。 说明:这里说的分三步是不考虑编译算一步,链接算一步这样划分的,前面的一些优化方法都是通过增加一些选项,然后编译链接就完成了,而PGO是需要两次编译链接和一次运行才是完整的,下面会详细分析。 能在程序运行一次的过程中就自动进行PGO当然是方便,但收集profile时总有额外开销,不一定适用于所有场景。
- 当前这个Multicore JIT的设计只针对程序启动速度优化,它只观察和记录JIT编译活动,生成的profile粒度太粗,仅是“被JIT编译过的方法的列表“,而不包含任何细粒度的profiling信息(例如说条件分支、虚方法的被调用对象的实际类型等)。
- 不但能通过profile信息来指导优化,还可以指导不做某些过于激进的优化,减少因过度优化而导致的“去优化”(deoptimization)。
- 介绍PGO 即 Profile-guided optimization(归档引导优化),是一种自适应优化手段,不需要对软件代码本身做出改进,即可获得性能的提升,目前已经应用于 GCC、VC++ 等常见的编译器中。
- JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。
- 一些开源项目像 Firefox 就默认使用 PGO 编译来优化性能,但是大部分软件上应用率并不高。
- 总体来说,使用PGO能辅助很多其他优化更好的进行,比如更精准的分支预测,提高指令cache的效率,更好的决定函数是否内联,更好的向量化决策(auto-vec),switch语句的优化等等。
- 这样才可以做到本文开头引用的那段文字所描述的优化。
另外,以下内容不保证对于所有版本的编译器都正确,编译器的实现也可能有一些变化之处,具体参考官方文档。
在正常执行时,每个有MSIL方法体的方法只有一次被编译的机会;一旦被编译过了就雷打不动了。 对单次执行来说,CLR这种“单层JIT编译、只编译一次“的模型意味着代码被编译的时候还一次都没被执行过,也就无从借助运行时收集的profile信息来做有针对性的优化。 在 Linux 内核上使用链接时优化并不是新概念,过去已有多家厂商发布了针对 Linux 内核的… 这是JIT编译的一种特殊做法,虽然没有脱离JIT编译的范畴但增加了一个自由度。 与之相对,自适应动态编译由于可以等程序执行了一段时间之后才做编译,所以有充分时间收集profile并利用profile来优化,经典例子就是收集分支跳转的次数,看taken分支还是not-taken分支的次数多。 这样才可以做到本文开头引用的那段文字所描述的优化。
EMS故障碼消除說明: 於EMS故障碼檢測模式中,同時長按SEL&ADJ鍵三秒即可消除。 上述步驟將消除故障碼,自行消除可能造成技師無法檢測判定。 自适应动态编译的思路就是把这种多次运行才能得到的好处压缩在一次运行中完成:执行引擎自动在开始的时候生成收集profile的代码,然后自动收集profile,最后自动利用profile来做优化编译。 这样不但用起来方便,而且可以保证收集到的profile能够反映本次运行的特征。 Native PGO的多次运行模型非常依赖于training run的代表性,如果其特征与后来实际运行的特征不匹配,那PGO“优化”反而会带来性能损失。 简单理解,就是在静态情况下,编译器是无法获取这些信息的。
注意ReJIT功能自身并不用于收集profile;收集profile的是CLR外部的managed profiler。 所以收集到的profile也无法供给CLR的JIT编译器使用。 但基于这个架构,后续开发完全可以添加更多功能,例如在recording mode中让JIT编译器生成收集profile的代码,收集细粒度profile(例如类型信息、分支跳转情况等),并将收集到的profile写入文件;后续执行就可以根据细粒度profile来做高度优化的编译。 自适应动态编译(adaptive dynamic compilation)也是一种动态编译,但它通常执行的时机比JIT编译迟,先让程序“以某种形式”先运行起来,收集一些信息之后再做动态编译。 这样的编译可以更加优化,可以很自然的融入PGO优化。
由香港SEO公司 featured.com.hk 提供SEO服務