使用CPU热点诊断CPU消耗高的问题

ARMS CPU热点作为一种监控诊断工具,通过持续剖析技术定时采集正在执行CPU线程的方法栈快照,定位CPU使用率高的根因。当系统CPU使用率较高时,ARMS CPU热点可为您快速定位导致CPU消耗高的相关业务逻辑方法栈。

重要

开启该功能会增加约5%额外CPU开销,使用前请提前预留相应量可用资源。

开启CPU热点

  1. 登录ARMS控制台,在左侧导航栏选择应用监控 > 应用列表

  2. 应用列表页面顶部选择目标地域,然后单击目标应用名称。

    说明

    语言列显示Java图标图标的应用为接入应用监控的应用,显示-图标的应用为接入可观测链路 OpenTelemetry 版的应用。

  3. 在左侧导航栏中单击应用设置,然后单击自定义配置页签。

  4. 持续剖析区域开启总开关,然后开启CPU热点开关,配置需要开启的应用实例的IP地址或者一组实例所属的网段地址。

  5. 在页面底部单击保存

    无需重启应用即可生效。

通过持续剖析查看CPU热点数据

示例:一个每秒在CPU上执行500 ms的方法。

public class CPUPressure {

    //请求入口方法
   public void runBusiness() {
        long start = System.currentTimeMillis(), period = 0;
        while (period <= 500L) {
            period = System.currentTimeMillis() - start;
        }
    }
}
  1. 登录ARMS控制台,在左侧导航栏选择应用监控 > 应用列表

  2. 应用列表页面顶部选择目标地域,然后单击目标应用名称。

    说明

    语言列显示Java图标图标的应用为接入应用监控的应用,显示-图标的应用为接入可观测链路 OpenTelemetry 版的应用。

  3. 在左侧导航栏单击持续剖析,在左侧实例列表中选择目标实例,然后在右侧页面设置数据展示时间。

  4. 在右侧查询页签,您可以筛选数据并查看聚合分析。

    说明

    性能分析类型:

    • CPU Time:CPU申请量热点剖析数据。

    • Allocated Memory:内存申请量热点剖析数据。

    • Allocations:内存申请次数热点剖析数据,可以查看哪些方法申请内存次数频繁。

    image

  5. 单击聚合分析,在新页面中选择性能分析类型CPU Time

    image

    图中左侧为本次调用中涉及的所有方法CPU资源使用情况列表,右侧为对应方法所有方法栈信息绘制的火焰图。其中:

    • Self列表示方法在自身的调用栈中所消耗的时间或资源,不包括其子方法调用所消耗的时间或资源。可以用于识别哪些方法在自身内部花费了大量的时间或资源。

    • Total列包含方法自身消耗的时间或资源,及其所有子方法调用所消耗的时间或资源。可以帮助了解整个方法调用栈中哪些方法贡献了最多的时间或资源。

    根据上图,进行如下分析:

    1. Self值从大到小排列,找到并单击Self值最大的方法java.lang.System.currentTimeMillis(),右侧火焰图中将会聚焦相关方法。

      image

    2. 聚焦后可以发现,java.lang.System.currentTimeMillis()就是右侧火焰图中的最宽栈顶方法。

    3. 由于该栈顶是JDK中的库函数,并非为业务方法,因此,沿着栈顶方法java.lang.System.currentTimeMillis()从下往上搜索,依次经过java.lang.System.currentTimeMillis() > com.alibaba.cloud.pressure.memory.CPUPressure.runBusiness(),而com.alibaba.cloud.pressure.memory.CPUPressure.runBusiness()属于所分析应用的业务方法,其耗时为28.63s,占到整张火焰图的91.44%,因此com.alibaba.cloud.pressure.memory.CPUPressure.runBusiness()是该火焰图所采集时段内资源占用较高的显著瓶颈所在,可以根据相关方法名,对业务中相关方法的逻辑进行梳理,查看是否存在优化空间。

通过上述分析,可以看到在1分钟内,com.alibaba.cloud.pressure.memory.CPUPressure.runBusiness()方法耗时28.63 s,与示例场景逻辑吻合。