4.7 PGO 优化

macOS、Linux 和 Windows 的构建过程提供了 profile-guided optimization (PGO) 的标志。 PGO 不是由 Python 团队创造的,而是包括 CPython 使用的编译器在内,许多编译器都有的一个特性。

PGO 的工作方式是进行初始编译后,通过运行一系列测试来分析应用程序。然后编译器会分析配置文件,并修改二进制文件以提高性能。

CPython 在分析阶段运行 python -m test --pgo,这会执行 Lib/test/libregrtest/pgo.py 中指定的回归测试。 之所以专门挑选这些测试,是因为它们使用了常用的 C 扩展模块或类型。

PGO 过程非常耗时,因此为了缩短编译时间,我已将其排除在本书提供的推荐步骤列表之外。

如果你想在生产环境中分发自定义编译版本的 CPython,那么应该在 Linux 和 macOS 上运行 ./configure 时加上 --with-pgo 标志,在 Windows 上运行 build.bat 时加上 --pgo 标志。

由于优化是针对执行分析的平台和架构的,PGO 配置文件无法在操作系统或 CPU 架构之间共享。 Python.org 上的 CPython 发行版已经进行了 PGO,因此如果你在未添加 PGO 编译选项的二进制文件上运行基准测试,那么它会比从 Python.org 下载的慢。

Windows、macOS 和 Linux 的 PGO 优化包括以下检查和改进:

  • 函数内联:如果一个函数经常被另一个函数调用,那么它将被内联或复制到调用函数中,以减少堆栈大小。

  • 虚调用推测和内联:如果一个虚函数调用频繁地指向某个特定函数,那么 PGO 可以插入一个条件执行的直接调用到那个函数。然后可以内联直接调用。

  • 寄存器分配优化:基于配置文件数据结果,PGO 将会优化寄存器分配。

  • 基本块优化:基本块优化允许将给定栈帧内临时执行的常用基本块放置在同一位置或一组页中。这可以最大限度地减少使用的页的数量,从而最大限度地减少内存开销。

  • 热点优化:可以优化程序执行时间最长的函数来加速。

  • 函数布局优化:在 PGO 分析调用图后,会把倾向于出现在相同执行路径中的函数移动到已编译应用程序的相同段中。

  • 条件分支优化:PGO 可以查看条件判断分支,如 if ... else ifswitch 语句,并找出最常用的路径。例如,如果 switch 语句中有 10 个 case 且 95% 的时间都使用了其中一个,那么该 case 将被移至顶部,以便在代码路径中立即执行。

  • 盲区分离:在 PGO 期间未调用的代码被移动到应用程序的单独段中。

Last updated