目前
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%。
网友评论