美文网首页
Android 获取APP自身的CPU使用率

Android 获取APP自身的CPU使用率

作者: 小强开学前 | 来源:发表于2022-09-11 23:47 被阅读0次

目前 top,dumpsys cpuinfo,/proc/stat这些都被谷歌以安全为由禁止访问了
但是性能监控(APM)的需求还是有的,这里也只是分享如何获取自身进程的CPU使用率

public class APM{

    // Linux 默认时钟频率为 100 HZ
    private int CLK_TCK = 100;
    // 上次的CPU使用时间
    private long lastUsedCPUTime = 0L;
    // 上次的CPU记录时间
    private long lastRecordCPUTime = SystemClock.uptimeMillis();
    // 存储 CPU 使用信息的文件
    private final File pidStatFile = new File("/proc/" + Process.myPid() + "/stat");
    // 获取 时钟频率 的命令
    private final String[] cmd = {"sh", "-c", "getconf CLK_TCK"};

   /**
     * 计算方法 ∆(uTime + sTime) / ∆upTimeMillis / 1000 * CLK_TCK / CORE_COUNT
     * 计算方法 进程运行时间片数 / (已过去时间 * 时钟频率 * 可用核心数)
     *
     * @return 当前CPU使用率%(from 0 to 100)
     */
    private float getCpuUsage() {
        try (FileInputStream inputStream = new FileInputStream(pidStatFile);
             InputStreamReader reader = new InputStreamReader(inputStream);
             BufferedReader bufferedReader = new BufferedReader(reader)
        ) {
            String line = bufferedReader.readLine();
            String[] res = line.split(" ");
            // 进程在用户态运行的时间
            long uTime = Long.parseLong(res[13]);
            // 进程在内核态运行的时间
            long sTime = Long.parseLong(res[14]);
            // 本次运行总时间
            long usedTime = (uTime + sTime) - lastUsedCPUTime;

            long currentTime = SystemClock.uptimeMillis();
            // 获得已过去时间 ms ==> s ==> Clock Tick
            float elapsedTime = (currentTime - lastRecordCPUTime) / 1000f * CLK_TCK;

            lastUsedCPUTime = uTime + sTime;
            lastRecordCPUTime = currentTime;

            float usage = usedTime / elapsedTime * 100;
            return usage / Runtime.getRuntime().availableProcessors();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0f;
    }

    /**
     * 确保时钟频率正确,以防厂商定制
     * 测试 坚果1 Android5.1 获取参数失败,但默认也是 100
     */
    private void configClkTck() {
        try {
            java.lang.Process process = Runtime.getRuntime().exec(cmd);
            try (InputStream inputStream= process.getInputStream();
                 InputStreamReader reader = new InputStreamReader(inputStream);
                 BufferedReader bufferedReader = new BufferedReader(reader)){
                CLK_TCK = Integer.parseInt(bufferedReader.readLine());
            }
            process.destroy();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

大致思路就是T1时间 uTime + sTime 与 T2时间 uTime + sTime 差值,除以总时间片数,当然还要考虑多核的情况。

  • uTime + sTime 可以获得此进程到现在为止已经使用的CPU时间片数

  • 另外还有两个参数可以获得此进程的子进程的 uTime + sTime, 叫做 cutime 和 cstime

  • CPU每有固定换片次数,这与CPU频率有关,Linux 一般固定为100,可以通过getconf CLK_TCK查询。

大概就是:

∆appCPUUsage / (∆time * CLK_TCK * coreCount)

自测与Debug环境下的TOP命令查看的结果相差不到1%。

相关文章

网友评论

      本文标题:Android 获取APP自身的CPU使用率

      本文链接:https://www.haomeiwen.com/subject/jowfortx.html