openEuler版本升级后CPU使用率异常升高
发表于 2025/09/12
0
作者|薛大量
现象描述
操作系统由openEuler 20.03升级到openEuler 22.03后,出现CPU使用率异常高,大量丢包的情况。
可能原因
经分析定位后,确认性能下降问题由openEuler 20.03升级到openEuler 22.03时,开源GCC 10引入的 "PR85678: Change default to -fno-common" 导致。该 PR 将默认编译选项 “-fcommon” 修改为 “-fno-common”。
在GCC中,编译选项 "-fcommon" 决定了C代码内未初始化的全局变量会作为一个弱符号(一个弱符号可定义在多个目标文件中,类型可不同,程序使用的编译器由GCC7.3.0升级到GCC10.3.1)被放在common块中,通过在链接时根据程序内各编译单元提供的信息,确定弱符号的大小,最终在输出文件的BSS段分配空间。但是根据C代码标准(ISO/IEC 9899:201x第6.9段第5点),"如果使用具有外部链接标识符的变量在表达式中使用时(除了作为 sizeof 运算符的参数,其结果是一个整数常量的一部分),在整个程序中应该存在唯一外部定义该标识符的实例;否则,最多只能存在一个外部定义",在各编译单元多次临时性定义未初始化的全局变量并放在common块中留给链接时决定,违反了C代码标准,同时会增加错误的风险,导致代码质量下降。因而,针对该现象将 "-fcommon" 修改成 "-fno-common" 后,原先未初始化的全局变量会直接被放在BSS段中,多重定义的问题会在链接时被识别为错误而被捕获。
放入BSS段后,GCC能够在链接前知晓这类变量相对于彼此的位置,那么就可以通过获取一个变量的地址(锚点),仅通过添加偏移量来访问其他变量,即纳入了 "-fsection-anchors" 的作用场景。编译选项 "-fsection-anchors" 会通过 "使用共享的锚点符号来访问附近的对象,以减少符号计算的数量,这种转换可以帮助减少某些目标上的全局偏移表(GOT)条目数以及GOT访问次数。"
GCC Internal中举了以下一个例子:由于GCC通常将每个静态对象视为一个单独的实体,以下函数foo的代码通常会计算三个独立的符号地址:a, b, c,
static int a, b, c;
int foo (void) { return a + b + c; }
通过"-fsection-anchors"的编译作用后,foo会利用x作为一个公共锚点 (section anchor) 访问变量,实际效果类似于以下的伪代码:
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
根据客户调试定位到的代码位置,变量 http_ctx_cnt作为一个先前放入common段的未初始化的全局变量,在GCC 10中会被放入BSS段,潜在成为"-fsection-anchors"的作用对象。而开启编译选项"-fsection-anchors"可获得的效果仍需要以根据实际业务的标准来决定。
rte_atomic32_t http_ctx_cnt;
function()
{
…..
Rte_atomic32_add_return(&http_ctx_cnt,1) > (int) max_sessions);
…..
}
当编译选项"-fsection-anchors"的作用范围扩大后,也会出现性能回退的情况。例如,在"-fsection-anchors"的使用场景中,每次访存都会经过锚点加偏移的计算,例如,访存 a 时,实际执行可能为 xr[&a - &x](偏移+访存) 而非 a (访存),造成额外开销;在最坏的情况下,代码中出现多个距离相近的锚点指向同一个对象(而非单个锚点通过位移指向多个距离相近的对象),同时该对象长期处于循环访存的情况下,锚点偏移访存造成的开销可能大于带来的收益,即会导致性能回退。该处的原子操作可能涉及到了类似的场景,http_ctx_cnt被捕获成为了"-fsection-anchors"的作用对象,最终导致性能下降。
影响分析
"-fsection-anchors" 作为 aarch64 架构的GCC中“-O1”的默认开启编译选项,对其他GCC行为无影响,仅在该业务模块关闭此选项不会造成功能及性能影响。
处理步骤
可以在该业务模块相关文件编译时,添加编译选项 "-fno-section-anchors" ,通过禁用 "section anchor" (锚点+偏移) 的选项,保证未初始化全局变量,例如http_ctx_cnt在放入BSS段后不会受到 "section anchor" 作用,来确保性能不会回退。