perf report中__mcount_internal与_mcount含义及高CPU占用原因
问题现象
使用Linux perf对C++应用ZManager做CPU性能采样时,生成的报告显示73%以上的CPU开销集中在libc-2.23.so的两个符号上:
59.19% ZManager libc-2.23.so [.] __mcount_internal 14.15% ZManager libc-2.23.so [.] _mcount
其余开销分散在vector操作、内存分配、锁操作等常规逻辑中,占比均不超过2%。
两个符号的具体含义
_mcount:是编译器插桩机制的标准入口函数。GCC在开启函数级追踪编译选项时,会在每一个函数的入口位置自动插入对_mcount的调用,这个函数本身逻辑非常轻,只作为钩子入口存在,作用是在函数正式执行业务逻辑前,跳转进入profiling统计流程。__mcount_internal:是_mcount背后的核心实现函数,负责完成函数调用栈记录、执行计数累加、追踪回调触发、父子函数调用关系维护等所有实际的profiling统计工作,_mcount的调用最终几乎都会进入这个内部函数执行逻辑。
高CPU占比的原因
这两个函数的高开销完全不是libc的正常业务开销,本质是你的应用二进制被编译时加入了全量函数插桩逻辑:
- 最常见的诱因是编译时添加了
-pg参数:这个参数是专门为gprof性能分析工具设计的,会给所有函数插入mcount调用,用来生成gprof需要的函数耗时、调用关系数据。如果编译完没有去掉这个参数就直接部署运行,哪怕你根本不启动gprof,每一次函数调用都会额外执行一遍mcount的统计逻辑,函数调用频次越高,这部分开销占比越大。 - 其他可能的诱因包括:编译时开启了
-finstrument-functions自定义函数插桩选项、链接了带mcount插桩的第三方性能分析/追踪库、误用了debug/profiling专用的库版本做编译链接。 - 你当前拿到的perf报告完全不能代表程序正常运行时的性能分布:超过七成的CPU都被插桩统计逻辑本身吃掉了,剩下不到三成的采样数据才是程序真实业务逻辑的开销。
修复方案
- 检查项目的编译配置(CFLAGS、CXXFLAGS、链接选项),删除
-pg、-finstrument-functions这类插桩相关的编译参数 - 排查所有链接的第三方静态库、动态库,确认链接的是正式发行的无插桩版本,不要链接用于调试、性能分析的特殊编译版本
- 重新编译正式Release版本时,确认开启
-O2或-O3优化等级,关闭所有profiling、调试相关的特殊选项,新的二进制运行时mcount相关的符号会完全消失,此时再用perf采样才能拿到真实的性能瓶颈数据。
内容的提问来源于stack exchange,提问作者liv2hak
相关产品推荐
相关产品推荐

