探究 Go Profile-Guided Optimizations(PGO)

本文介绍了 Go 语言中 Profile-Guided Optimizations(PGO)的概念,这是一种利用运行时信息进行编译优化的技术。在 Go 1.20 版本中,PGO 主要用于内联函数,通过 profiling 数据来指导优化决策。通过实例展示了 PGO 如何提高代码执行速度,通常可以带来 5%-15% 的性能提升。未来,Go 编译器还将考虑应用 PGO 于逃逸分析和 devirtualization 等领域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

> Profile-Guided Optimizations可以理解为一种运行时编译器优化,在下面描述中用 PGO 来当做缩写

使用 PGO 在不修改代码的前提下来提高代码执行速度。

在 Polar Signals,后端代码 100% 都是用 Go 写的。因此,自从2021年底谷歌的 Go 编译器团队开始对 PGO 进行原型设计时,我们就非常兴奋。在这个伯克利,我们将会描述一下什么是 PGO,它是如何工作的,以及为什么它是令人兴奋的一个工具。

Go 编译器对 PGO 的支持目前定在 1.20 版本(根据以前的版本可能会在 2023 年 2 月/ 3 月发布,而这个issue现在是在活动栏中)。

什么是 PGO ?

总的来说,PGO 就是使用以 profiling 数据格式 的 runtime 信息,在编译时进行优化,这个其实不是一个好的思路,但通过 runtime 所提供的信息,可以预期会有一个正向的积极影响。

Go 编译器引入的第一个 PGO 是使用 profiling 数据来内联函数,否则可能不会内联。如果你不熟悉内联函数或者想要重新复习一下,可以看一下我们发布的博客《为什么编译器内联函数如此重要》。

所以 PGO 到底是如何进行函数内联的呢?Go 编译器对一个函数的内联成本有一个启发式的判断。通常情况下,如果内联成本高于 80,那它是不会被内联的。然而,在 PGO 的加持下如果 profiling 数据建议这个函数能在内联后获得提升,那即使函数的内联成本高于 80,也依旧会被内联。

让我们来看一个具体的例子,在写这篇文章时,使用目前提议后对 Go 编译器的修改。

如果你想跟随着这篇博文,在你的代码库中尝试 PGO ,或者只是复制这篇博文所演示的内容,请勾选该补丁并使用它编译 Go runtime:

bash
git clone https://go.googlesource.com/go
cd go
git fetch https://go.googlesource.com/go refs/changes/63/429863/3 && git checkout -b change-429863 FETCH_HEAD
cd src
./all.bashcd
..export PATH="(pwd)/bin:PATH" # or add the path to your bashrc/zshrc
### AOT 和 JIT 编译在 Android 系统中的协同工作原理 Android 的 ART (Android Runtime) 使用两种主要的编译方式来提升应用性能:AOT(Ahead-of-Time)和 JIT(Just-in-Time)。这两种技术各有优劣,在实际运行过程中会相互配合。 #### AOT 编译 AOT 是一种静态编译模式,它会在应用程序安装阶段将 Dex 文件转换为本地机器码并存储到 OAT 文件中。这种方式的优点在于减少了首次启动时间以及后续运行时的 CPU 负载[^1]。然而,由于设备硬件差异较大,提前生成的代码可能无法针对具体场景做最优调整。 #### JIT 编译 相比之下,JIT 则是在程序执行期间动态地将字节码转化为高效的原生指令序列,这允许系统基于当前使用的处理器架构做出更精确的选择从而提高效率;另外一方面也可以收集关于哪些部分被频繁调用的信息以便日后改进这些热点区域的表现效果[^2]. 当两者结合起来看的时候我们可以发现它们之间存在着互补关系:AOT 提供了一个快速进入状态而无需等待解释过程完成的机会;与此同时JIT则持续监测正在被执行的部分并通过不断重新编译那些最常访问的地方使得长期来看可以获得更高的整体效能. ### dex2oat 工具及其使用方法 dex2oat 实际上就是用来实现上述提到过的由 .class -> .dex 再经过一系列处理最终得到适合目标平台特性的可直接加载执行版本(.odex 或者 .art). 它位于 `/system/bin/` 下面,并且可以通过命令行参数控制不同的行为比如设置 `--compiler-filter=` 来指定采用何种策略进行优化(`verify`, `quicken`, `speed`, or `speed-profile`)等操作。 对于 Profile-Guided Optimization(PGO), 这种技术利用历史数据帮助决定应该重点考虑哪一部分代码来进行更加激进形式上的变换以期达到更好结果的目的之一就在于减少不必要的计算量同时增加缓存命中率进而改善用户体验质量方面起到积极作用。要启用 PGO 需要在构建流程里加入相应标记并且确保存在有效的 profiling 数据可供参考。 以下是简单的示例展示如何手动触发一次 dex2oat 流程: ```bash /system/bin/dex2oat \ --runtime-arg -Xms64m \ --runtime-arg -Xmx512m \ --image=/path/to/boot.art \ --oat-file=/output/path/app.oat \ --dex-file=/input/path/classes.dex \ --instruction-set=arm64 \ --compiler-filter=speed-profile ``` 此脚本片段展示了基本语法结构其中包含了几个重要组成部分如内存分配大小定义(-Xms,-Xmx),引导镜像路径设定(image),输出输入文件定位(oat-file,dex-file),体系结构声明(instruction-set)还有最后那个影响程度极大的过滤级别(compiler-filter). ### 结论 综上所述,AOT与JIT共同构成了现代安卓平台上复杂却高效的应用执行框架基础. 同样地,Dex2Oat作为连接二者桥梁角色不可或缺.PGO更是进一步增强了这一链条的有效性和针对性.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值