brpc CPU Profiler 使用指南:基于 SIGPROF 采样的热点函数分析
发布时间:2026/9/14 2:13:49 锦皓数字建站

brpc CPU Profiler 使用指南基于 SIGPROF 采样的热点函数分析【免费下载链接】brpcbrpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. brpc means better RPC.项目地址: https://gitcode.com/GitHub_Trending/brpc/brpcbrpc 内置了基于 gperftools 的 CPU profiler可以直接通过 builtin service 页面/hotspots/cpu或 pprof 工具对运行中的 server 进行采样找出程序中的热点函数。本文以 docs/cn/cpu_profiler.md 为主线结合仓库中 hotspots_service.cpp 等服务端实现完整讲解从开启、采样、查看、调参到火焰图的全部实战细节。背景为什么需要 CPU profiler在高性能 RPC 服务搜索、存储、机器学习、广告推荐等场景的开发与调优中定位 CPU 热点是性能优化的第一步。brpc 借助 gperftools 的采样型 profiler以较小的开销周期性采集各活跃线程的调用栈最终汇总成包含函数调用关系的调用图帮助开发者直观地找到最大最粗的热点路径。CPU profiler 的原理是在定期被调用的 SIGPROF handler 中采样所在线程的栈。由于 handlerLinux 2.6 之后会被随机摆放在活跃线程的栈上运行CPU profiler 运行一段时间后能以很大的概率采集到所有活跃线程中的活跃函数最后根据栈所代表的函数调用关系汇总为调用图并把地址转换成符号就得到了最终的分析结果图。采样频率由环境变量CPUPROFILE_FREQUENCY控制默认 100即每秒采样 100 次每 10ms 一次。在实践中 CPU profiler 对原程序运行的影响不明显。开启方法1. 链接libtcmalloc_and_profiler.a要使用 CPU profiler程序必须链接 gperftools 提供的libtcmalloc_and_profiler.abrpc 构建产物output/lib目录下自带该库由 gperftools 源码编译而来。需要注意链接该库的同时也就开启了 tcmalloc。不建议单独链接 cpu profiler 而不链接 tcmalloc否则可能越界访问导致 crashgperftools 官方说明详见其 README 第 226 行附近而由于 tcmalloc 可能不及时归还内存越界访问不一定会 crash这类问题难以排查。如果 tcmalloc 使用 frame pointer 而不是 libunwind 来回溯栈请务必在CXXFLAGS或CFLAGS中加上-fno-omit-frame-pointer否则函数间的调用关系会丢失最终生成的图片里都是彼此独立的函数方框无法形成有效调用图。2. 定义宏BRPC_ENABLE_CPU_PROFILER在编译参数中加入-DBRPC_ENABLE_CPU_PROFILER。关键点该宏必须定义在引用了 brpc 头文件channel.h 或 server.h的代码里。例如 A 模块引用 B 模块而 B 模块在实现中引用了 brpc 头文件那么必须在B 模块的编译参数上加BRPC_ENABLE_CPU_PROFILER在 A 模块加是没有用的。从源码可以印证这一点仓库中的 profiler_linker.h 定义了ProfilerLinker内联构造函数当BRPC_ENABLE_CPU_PROFILER或其旧名BAIDU_RPC_ENABLE_CPU_PROFILER被定义时该构造函数会执行cpu_profiler_enabled true并通过一个永假的if (PROFILER_LINKER_DUMMY ! 0)分支强制链接ProfilerStart()/ProfilerStop()等符号。这个内联构造函数包含在用户的编译单元中因此只有定义了宏的那个编译单元模块才能真正启用 profiler。cpu_profiler_enabled的全局定义位于 index_service.cpp/index页面会据此显示 CPU profiling 是否处于(disabled)状态服务端 server.cpp 中的PrintEnabledProfilers也会把启用的 profiler 暴露到rpc_profilers这个 bvar 中可用来确认启用状态。3. 仅 client 或未使用 brpc 的场景如果只是 brpc client或根本没有使用 brpc比如只想给某个普通多线程程序做 CPU profiling请参考 dummy_server.md通过启动一个内置了各类 builtin service 的 dummy server把 profiling 请求转发到目标进程。注意关闭 Server 端认证采样期间访问 profiling 页面时如果 Server 开启了认证如 giano authenticator会看到类似下面的报错且 server 端会出现认证失败的 FATAL/WARNING 日志$ tools/pprof --text localhost:9002/pprof/profile Use of uninitialized value in substitution (s///) at tools/pprof line 2703. http://localhost:9002/profile/symbol doesnt existserver 端日志FATAL: 12-26 10:01:25: * 0 [src/brpc/policy/giano_authenticator.cpp:65][4294969345] Giano fails to verify credentical, 70003 WARNING: 12-26 10:01:25: * 0 [src/brpc/input_messenger.cpp:132][4294969345] Authentication failed, remote side(127.0.0.1:22989) of sockfd5, close it因此执行 profiling 前应关闭 Server 端的认证。查看方法方式一builtin service 页面/hotspots/cpu打开http://server_addr/hotspots/cpu即可看到 CPU 热点分析页面。该服务由HotspotsService提供注册信息见 hotspots_service.cpp同时还有/hotspots/heap、/hotspots/growth、/hotspots/contention、/hotspots/iobuf等兄弟入口。页面顶部还会根据cpu_profiler_enabled显示 CPU profiler 是否被启用。方式二pprof 命令行工具仓库自带 tools/pprofgperftools 的 perl 版 pprof 脚本也可以使用 gperftools 自带的 pprof。命令行形式如下tools/pprof --text localhost:9002/pprof/profile一次真实运行的例子统计运行在本机 9002 端口的 server时长 5 秒$ tools/pprof --text 0.0.0.0:9002 --seconds5 Gathering CPU profile from http://0.0.0.0:9002/pprof/profile?seconds5 for 5 seconds to /home/gejun/pprof/echo_server.1419501210.0.0.0.0 Be patient... Wrote profile to /home/gejun/pprof/echo_server.1419501210.0.0.0.0 Removing funlockfile from all stack traces. Total: 2946 samples 1161 39.4% 39.4% 1161 39.4% syscall 248 8.4% 47.8% 248 8.4% bthread::TaskControl::steal_task 227 7.7% 55.5% 227 7.7% writev 87 3.0% 58.5% 88 3.0% ::cpp_alloc 74 2.5% 61.0% 74 2.5% __read_nocancel 46 1.6% 62.6% 48 1.6% tc_delete 42 1.4% 64.0% 42 1.4% brpc::Socket::Address 41 1.4% 65.4% 41 1.4% epoll_wait 35 1.2% 66.7% 35 1.2% memcpy 33 1.1% 67.7% 33 1.1% __pthread_getspecific 33 1.1% 68.8% 33 1.1% brpc::Socket::Write 33 1.1% 69.9% 33 1.1% epoll_ctl 28 1.0% 70.9% 42 1.4% brpc::policy::ProcessRpcRequest 27 0.9% 71.8% 27 0.9% butil::IOBuf::_push_back_ref 27 0.9% 72.7% 27 0.9% bthread::TaskGroup::ending_sched省略--text则进入交互模式$ tools/pprof localhost:9002 --seconds5 Gathering CPU profile from http://0.0.0.0:9002/pprof/profile?seconds5 for 5 seconds to /home/gejun/pprof/echo_server.1419501236.0.0.0.0 Be patient... Wrote profile to /home/gejun/pprof/echo_server.1419501236.0.0.0.0 Removing funlockfile from all stack traces. Welcome to pprof! For help, type help. (pprof) top Total: 2954 samples 1099 37.2% 37.2% 1099 37.2% syscall 253 8.6% 45.8% 253 8.6% bthread::TaskControl::steal_task 240 8.1% 53.9% 240 8.1% writev 90 3.0% 56.9% 90 3.0% ::cpp_alloc 67 2.3% 59.2% 67 2.3% __read_nocancel 47 1.6% 60.8% 47 1.6% butil::IOBuf::_push_back_ref 42 1.4% 62.2% 56 1.9% brpc::policy::ProcessRpcRequest 41 1.4% 63.6% 41 1.4% epoll_wait 38 1.3% 64.9% 38 1.3% epoll_ctl 37 1.3% 66.1% 37 1.3% memcpy 35 1.2% 67.3% 35 1.2% brpc::Socket::Address在交互模式中输入help可以查看全部命令例如top查看热点函数排行、gv生成调用图等。控制采样频率在程序启动前设置环境变量即可export CPUPROFILE_FREQUENCYxxx默认值为100即每秒 100 次采样每 10ms 一次。调高频率可以获得更细粒度的采样统计但也会相应增大对目标程序运行的影响和 profile 文件体积。控制采样时间在 URL 上追加?seconds秒数参数即可例如/hotspots/cpu?seconds5表示采样 5 秒。从 hotspots_service.cpp 的ReadSeconds实现可以看到seconds参数从 HTTP query 中解析缺省时使用DEFAULT_PROFILING_SECONDS值为 10且结果会被FLAGS_max_profiling_seconds封顶防止过长的采样请求。对应的 pprof 命令行写法是pprof --text localhost:9002 --seconds5。结果图解读下图是一次运行 CPU profiler 后的结果即文首展示的调用图左上角是总体信息包括采样时间、程序名、总采样数等。View 框中可以选择查看之前运行过的 profile 结果Diff 框中可选择查看与之前结果的变化量。这些历史记录在服务重启后被清空。代表函数调用的方框中的字段从上到下依次为函数名、这个函数本身除去所有子函数占的采样数和比例、这个函数及其调用的所有子函数累计的采样数和比例。采样数越大框越大。方框之间连线上的数字表示被采样到的上层函数对下层函数的调用数数字越大线越粗。热点分析一般从找到最大的框、最粗的线开始考察其来源及去向从而定位性能瓶颈所在。MacOS 的额外配置在 MacOS 下gperftools 中的 perl 版 pprof 脚本无法把函数地址转变成函数名解决办法是安装 standalone pprof并把下载的 pprof 二进制文件路径写入环境变量GOOGLE_PPROF_BINARY_PATH。从源码看hotspots_service.cpp 在 MacOS 分支会读取该环境变量并检查文件是否存在不存在时 profiling 请求会被拒绝返回FORBIDDEN图形渲染时也改用该二进制--dot/--text参数风格而不是 perl 脚本。安装 llvm-symbolizer将函数符号转化为函数名直接用 brew 安装即可brew install llvm。火焰图如果希望结果以火焰图的方式展示需要下载并安装 FlameGraph 工具将环境变量FLAMEGRAPH_PL_PATH正确设置到本地的/path/to/flamegraph.pl然后启动 server。从源码看hotspots_service.cpp 在 Linux 分支读取FLAMEGRAPH_PL_PATH若未设置而请求display_typeflame会直接返回错误提示火焰图渲染时 pprof 输出--collapsed格式并经flamegraph.pl转换图片宽度由 gflagmax_flame_graph_width默认 1200控制见 hotspots_service.cpp。在页面上通过?display_typeflame即可切换火焰图展示。常见问题速查现象原因解决办法调用图中方框彼此独立、无连线tcmalloc 用 frame pointer 回溯栈但编译时省略了 frame pointer编译参数加-fno-omit-frame-pointer/index页面显示 CPU profiling(disabled)未定义BRPC_ENABLE_CPU_PROFILER或宏定义在了错误的模块在引用 brpc 头文件的模块编译参数中加-DBRPC_ENABLE_CPU_PROFILERpprof 报Use of uninitialized value ... /profile/symbol doesnt existServer 开启了认证关闭 Server 端认证后再 profiling/hotspots/cpu返回 CPU profiler is not enabled未链接libtcmalloc_and_profiler.a链接该库并定义宏见上文开启方法MacOS 下无法将地址转成函数名perl pprof 在 MacOS 上的限制设置GOOGLE_PPROF_BINARY_PATH并安装 llvm-symbolizer火焰图无法生成未设置FLAMEGRAPH_PL_PATH安装 FlameGraph 并设置环境变量后重启 server通过上述步骤开发者即可在 brpc 服务上快速定位 CPU 热点链接libtcmalloc_and_profiler.a、在正确的编译单元定义BRPC_ENABLE_CPU_PROFILER、通过/hotspots/cpu或tools/pprof按需采样并结合调用图与火焰图进行深度分析。更多 profiling 相关能力heap/growth/contention/iobuf可继续阅读 docs/cn/heap_profiler.md 与 docs/cn/contention_profiler.md。【免费下载链接】brpcbrpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. brpc means better RPC.项目地址: https://gitcode.com/GitHub_Trending/brpc/brpc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。