Android 獲取APP自身的CPU使用率

目前 top,dumpsys cpuinfo,/proc/stat這些都被谷歌以安全為由禁止訪問了
但是性能監(jiān)控(APM)的需求還是有的,這里也只是分享如何獲取自身進(jìn)程的CPU使用率

public class APM{

    // Linux 默認(rèn)時(shí)鐘頻率為 100 HZ
    private int CLK_TCK = 100;
    // 上次的CPU使用時(shí)間
    private long lastUsedCPUTime = 0L;
    // 上次的CPU記錄時(shí)間
    private long lastRecordCPUTime = SystemClock.uptimeMillis();
    // 存儲(chǔ) CPU 使用信息的文件
    private final File pidStatFile = new File("/proc/" + Process.myPid() + "/stat");
    // 獲取 時(shí)鐘頻率 的命令
    private final String[] cmd = {"sh", "-c", "getconf CLK_TCK"};

   /**
     * 計(jì)算方法 ?(uTime + sTime) / ?upTimeMillis / 1000 * CLK_TCK / CORE_COUNT
     * 計(jì)算方法 進(jìn)程運(yùn)行時(shí)間片數(shù) / (已過去時(shí)間 * 時(shí)鐘頻率 * 可用核心數(shù))
     *
     * @return 當(dāng)前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(" ");
            // 進(jìn)程在用戶態(tài)運(yùn)行的時(shí)間
            long uTime = Long.parseLong(res[13]);
            // 進(jìn)程在內(nèi)核態(tài)運(yùn)行的時(shí)間
            long sTime = Long.parseLong(res[14]);
            // 本次運(yùn)行總時(shí)間
            long usedTime = (uTime + sTime) - lastUsedCPUTime;

            long currentTime = SystemClock.uptimeMillis();
            // 獲得已過去時(shí)間 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;
    }

    /**
     * 確保時(shí)鐘頻率正確,以防廠商定制
     * 測(cè)試 堅(jiān)果1 Android5.1 獲取參數(shù)失敗,但默認(rèn)也是 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時(shí)間 uTime + sTime 與 T2時(shí)間 uTime + sTime 差值,除以總時(shí)間片數(shù),當(dāng)然還要考慮多核的情況。

  • uTime + sTime 可以獲得此進(jìn)程到現(xiàn)在為止已經(jīng)使用的CPU時(shí)間片數(shù)

  • 另外還有兩個(gè)參數(shù)可以獲得此進(jìn)程的子進(jìn)程的 uTime + sTime, 叫做 cutime 和 cstime

  • CPU每有固定換片次數(shù),這與CPU頻率有關(guān),Linux 一般固定為100,可以通過getconf CLK_TCK查詢。

大概就是:

?appCPUUsage / (?time * CLK_TCK * coreCount)

自測(cè)與Debug環(huán)境下的TOP命令查看的結(jié)果相差不到1%。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容