导读:本文探索&研究了大规模C/C++服务编译性能优化相关技术,优化服务性能,降低机器成本,同时为了支持规模推广应用,降低业务线接入成本,保障优化效果,进行面向云上微服务,开展平台化优化服务系统OMAX建设,并在百度推荐系统上大规模应用,取得线上服务CPU性能优化10%+和上线速度提升40%+双收益,优化后服务运行稳定,性能收益持续。
一、背景
随着大型互联网公司的业务不断发展,后端C++模块的逻辑处理越来越复杂,且参与开发人员众多,代码质量参差不齐,服务面临性能不断退化风险,大型程序模块,常见的通过代码上优化,主要存在以下问题:
-
成本高:典型推荐业务服务海量代码,逻辑功能复杂,有的往往需要深入理解业务进行优化,优化门槛高
-
效率低:模块迭代频繁,定向优化,没有一定的通用性和可持续性,往往随着迭代优化逐渐消失优势,需要不断循环往复投入开展优化
二、编译优化技术简介
编译优化技术,主要通过编译器或者优化工具框架来优化改写代码实现,实现性能提升,同时保障和未优化时功能上一致,对于代码开发者透明,这样可降低人工代码优化成本,提升优化效率,且可持续解决一类性能问题。
目前编译性能优化技术,按照编译过程来划分,主要有编译期,链接期和编译后的优化,下面简要介绍下这些优化技术特点,使用方式和优化效果等情况。
2.1 编译期
-
基础参数优化
在程序编译期间进行的优化,主要是基于编译器提供的能力,在不同的场景,综合编译时间,编译产出体积大小、性能优化幅度和CPU硬件支持等权衡选择最合适的优化参数,各参数优化汇总如下表:
类别 |
选项 |
优化效果 |
主要优缺点 |
备注 |
O系列 |
-O0 |
减少编译时间,使调试产生预期的结果 |
优点:方便程序调试 缺点:无优化 |
默认选项 |
-O/-O1 |
优化编译需要更多的时间,对于一个大函数来说,需要更多的内存,降低代码体积大小,优化执行时间,不会使用需要大量编译时间的优化 |
优点:相对O0进一步提升优化效果 |
||
-O2 |
启用-O1所有优化之外,还会采用几乎所有的目标配置支持的优化算法,用以提高目标代码的运行速度 |
优点:相对O1进一步提升优化效果 缺点:增加编译时间和体积大小 |
性能优化优先 |
|
-O3 |
启用所有-O2优化,还开启其它优化,如一般采取很多向量化算法,提高代码的并行执行程度,利用现代CPU中的流水线,Cache机制 |
优点:相对O2进一步提升优化效果 缺点:增加编译时间和目标体积大小 |
追求性能较大优化 |
|
-Ofast |
启用所有-O3优化,还开启并非对所有符合C++标准的优化 |
优点:相对O3进一步提升优化效果 缺点:不严格遵循语言标准,存在一定未知问题,如禁用符合IEEE标准的浮点,这可能会导致计算不准确 |
追求性能最大优化 |
|
-Og |
启用所有O1除不影响调试的优化,保持快速编译和良好的调试体验 |
优点:快速编译,保持优化对调试友好 缺点:损失一些优化效果 |
适合开发调试期场景,使用优于O0 |
|
-Os |
启用所有通常不会增加代码大小的-O2优化。它还执行旨在减少代码大小的进一步优化 |
优点:优化产出bin大小 缺点:损失一些优化效果 |
适合磁盘空间受限的运行场景 |
|
-Oz |
主要以优化bin体积大小为主,启用大部分O2优化 |
优点:优化产出bin大小 缺点:损失一些优化效果 |
和Os类似 |
|
CPU硬件扩展指令集 |
MMX |
多媒体信息的处理能力,64位整型 |
优点:高效数值、媒体,字符串,文体计算 缺点:需要CPU硬件支持 |
|
SSE (-msse, -msse2, -msse3, -msse4.1 -msse4.2) |
SSE:128位浮点运算 SSE2: 整型数据的支持,支持双精度浮点数运算,CPU快取的控制指令 SSE3: 寄存器的局部位之间的运算,如高位和低位之间的加减运算;浮点数到整数的转换,以及对超线程技术的支持 SSE4: 高性能库函数,字符串,文本处理 |
|||
AVX (-mavx, -mavx2, -mavx512 -mamx) |
AVX: 256位浮点运算 AVX256:对256位整型数据的支持,三运算指令 AVX512:512位运算 AMX:矩阵计算(2022) |
|||
代码生成方式 |
fpic |
生成相对位置无关的代码 |
优点:多应用共享代码段,节省内存空间占用 缺点:地址跳转处理,性能非最佳 |
适用so库形式 |
fno-pic |
生成位置相关的代码 |
优点:相对pic性能没有相对地址寻址,性能处理上较好 缺点:相同代码,每个进程持有一份拷贝,浪费内存空间 |
静态库 |
优化效果:
通过测试程序(排序算法),验证下参数类优化效果,测试O3优化情况下,相