常见 CPU 性能问题
你所负责的服务(下称:服务)是否遇到过以下现象:
休息的时候,手机突然收到大量告警短信,提示服务的 99.9 line 从 20ms 飙升至 10s;
正在敲代码实现业务功能时,收到业务/客服同事电话,反馈系统打不开;
下班后,收到运维同学电话,服务器监控告警提示“某个机器的负载(Load Average)从 0.1、0.5、0.8 突然间飙升至 9.73、10.67、10.49”。
结果:引发雪崩的场景如下图所示:
通常造成这几种现象的根本原因主要有以下 3 点。
服务在某个时间点运行了某一个定时器,但因为最近业务数据量增加,导致提取了大量数据到服务进行计算。
外部系统因为系统问题/数据量增加/逻辑修改,向消息中间件推送比平常多 10 倍的消息,此时服务消费了 MQ 消息,将消息内容放入一个新线程进行异步处理。而给消息中间件返回消息已处理完成,导致消息中间件一直给服务推送消息。
上线一个可以从 C 端触发需要大量 CPU 计算的功能,上线后使用的用户比预估量高 5 倍。
我们再来回顾一下之前的过程,如下图所示:
从现象到结果(CPU 问题),再到追溯原因这一过程,通常是通过对时间点、查日志、找上下游问题、Code Review、推测出问题代码,从而得出最终结论。但这种方式的缺点是耗时较长,且不能保证得到的结果一定是真实的。
利用工具定位 CPU 性能问题
借助Flame Graph(下称 CPU 火焰图),来定位 CPU 性能问题。
在实际工作中,使用 CPU 火焰图用于量化框架中的性能,包括代码编译消耗的时间、代码缓存、其他系统内库及内核代码执行的时间,通常用于定位 CPU 使用率问题。生成火焰图的方式有基于 Perf 或者Arthas。
利用 Perf 生成火焰图
从 Linux 系统原生提供的性能分析工具 perf 命令(performance 的缩写)说起,该命令执行后,会返回 CPU 正在执行的函数名以及调用栈(stack)。 通常,它的执行频率是 99Hz(每秒 99 次)。如果 99 次都返回同一个函数名,那就证明 CPU 同一秒钟都执行同一个函数,可能存在性能问题。具体可以通过执行以下 perf 命令获取对应的性能日志:
1 perf record -F 99 -p PID -g