背景
随着字节跳动的业务迅速增长,微服务的性能优化工作显得尤为重要,对于头部应用来说,提升若干百分点的性能也能为公司节省巨大的服务器资源成本。
编译器优化是软件性能优化的一种常用方法,相比其它特定的性能优化方法,它的适用性更广,能更全面地获得性能收益,从而降低成本。编译反馈优化(PGO)是常见的编译器的优化方法,字节跳动 STE 团队在编译反馈优化技术方向进行了持续的探索,并在字节跳动业务上积极地开展了实践工作,成功将编译反馈优化技术大规模落地于字节跳动业务,为公司节省了大量资源。
PGO简介
PGO(Profile-guided optimization)通常也叫做 FDO(Feedback-directed optimization),它是一种编译优化技术,它的原理是编译器使用程序的运行时 profiling 信息,生成更高质量的代码,从而提高程序的性能。
传统的编译器优化通常借助于程序的静态分析结果以及启发式规则实现,而在被提供了运行时的 profiling 信息后,编译器可以对应用进行更好的优化。通常来说编译反馈优化能获得 10%-15% 的性能收益,对于特定特征的应用(例如使用编译反馈优化 Clang本身)收益高达 30%。
编译反馈优化通常包括以下手段:
编译器需要 profiling 信息对应用进行优化,profile 的获取通常有两种方式:
Instrumentation-based PGO 的流程分为三步骤:
Instrumentation-based PGO 对代码插桩包括:
1. 插入计数器(counter)
2. 插入探针(probes)
收集间接函数调用地址(indirect call addresses)。
收集部分函数的参数值。
Sample-based PGO 的流程同样分为三步骤:
其中步骤2采集的数据为二进制级别采样数据(例如 linux perf 使用 perf record 命令收集得到 perf.data 文件)。二进制采样数据通常包含的是程序的 PC 值,我们需要使用工具,读取被采样程序的调试信息(例如使用 AutoFDO 等工具),将程序的原始二进制采样数据生成程序源码行号对应的采样数据,提供给编译器使用。
探索与落地
对比 sampled-based PGO,Instrumentation-based PGO 的优点采集的性能数据较为准确,但繁琐的流程使其在字节跳动业务上难以大规模落地,主要原因有以下几点:
使用 Sample-based PGO 方案可以有效地解决以上问题:
我们的目标是在字节跳动业务上大规模落地 PGO 技术,使字节跳动大量的应用能够从 PGO 技术中受益。PGO 本身是一项较为成熟的编译器优化技术,我们面临的主要问题为如何简化 PGO 繁琐的流程,自动化数据采集与优化流程,保证优化的可靠性。我们设计了系统解决这些问题,该系统的架构如图所示:其中包含的主要任务有:
集群维度的业务性能数据采集、维护与处理。
业务二进制与调试信息维护。
采样数据的查询与使用。
生成编译器可用的信息(LLVM profile)。
Profile 更新,业务性能测试与发版上线。
我们做了大量的前期工作,在 SPEC CPU2017 等 benchmark 上进行了 PGO 测试与结果分析,基于测试结果得出结论,包括:不同采样事件以及 LBR 数据对 Profile 准确度的影响,单机采样频率与额外性能开销之间的联系,集群采样数据聚合策略以及样本数量与优化效果的联系等。
我们在字节跳动服务器集群的物理机实例中部署了采样程序,该程序在后台以用户无感知的方式进行着性能数据的常态化采集工作,并将采集的性能数据上传。原始数据被解析处理后,最终维护在采样数据库中。
对于每一条采样记录,我们会维护它的原始信息,以及额外的元数据,这些信息包括:
采样地址
采样的 LBR(last branch record)数据
采样事件类型
采样所属二进制的 ID
采样业务的 PSM
其它元数据
我们搭建了二进制仓库,维护着所有线上运行的二进制以及其描述信息。对于加入到二进制仓库的二进制,系统会触发任务对其进行处理,提取 PGO 任务所需的符号信息,维护在指定的数据库中。
对于符号信息的查询,系统会返回指定二进制的 PC 值对应的 inline stack 信息,供 PGO 任务使用。
我们搭建了 PGO 平台,供业务用户使用 PGO 优化流程。业务接入 PGO 优化流程,首先需要通过平台指定策略。策略的作用是:
Profile 文件会被策略定期更新,业务开发同学在构建时通过选项控制使用 profile 编译得到 PGO 优化后的二进制版本,进行常规的版本发布流程,性能对比测试,决定是否上线优化版本。
我们在字节跳动内部头部 30+ 应用上落地了 PGO 优化流程,业务均获得明显的 CPU 以及延迟收益,平均获得了超过 5% 的 CPU 收益。
PGO 技术大规模在字节跳动业务落地实践后取得了显著收益,在其过程中,STE 团队也克服了诸多技术难题:完成了集群维度的数据采集工作,保证了数据的准确性同时做到了对业务无感知;在业务快速迭代的现状下,完成了二进制仓库的建设,规范了二进制符号信息的查询流程;搭建了 PGO 优化平台,简化了流程,业务方在构建程序时只需添加指定编译选项,大幅降低业务使用 PGO 的成本;在业务程序组成复杂依赖众多的现状下,分析预编译库的热点信息以及 PGO 效果不及预期的原因,推进了源码依赖的编译流程;同一个程序有可能被多个业务使用,在不同使用场景、时间段下,程序特征会有明显区别,我们在系统设计层面,有效地解决了该问题。
STE 团队会在后续的工作中完善已有系统,并对 PGO 技术进行持续的探索。包括支持 PGO 与 LTO 对业务的共同优化,在 PGO 平台引入 post-link time optimizer 对二进制进行优化,实现基于采样数据的软件预取优化等等,使字节跳动业务从中获得更大的受益。
|