目前
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%。