通过查看系统cpu信息可以监控系统的程序运行状况以及系统状况,对后续的性能优化、故障诊断、资源管理、安全性等等都非常重要。
总所周知安卓基于Linux,查看cpu相关信息的方法基本相同,但是部分参数与linux略有区别,这里只针对安卓上的部分参数作基本解读
adb shell top 或adb shell Enter(回车) top
任务(进程) 系统现在共有592个进程,其中处于运行中的有2个,590个在休眠(sleep),stoped状态的有0个,zombie状态(僵尸)的有0个
内存状态: 物理内存总量 (3.5G) 使用中的内存总量(3.4G) 空闲内存总量(59Mb) 缓存的内存量(15Mb)
1TB=1024GB ,1GB=1024MB ,1MB=1024KB ,1KB=1024字节。
swap交换分区: 交换区总量(2.0G) 使用的交换区总量(98Mb) 空闲交换区总量(1.9G) 缓冲的交换区总量(1.4G)
800%cpu 7%user 0%nice 21%sys 766%idle 0%iow 4%irq 1%sirq 0%host
cpu状态
800%cpu – CPU总量 1个核是100%
7%user – 用户空间占用CPU的百分比。
0%nice – 改变过优先级的进程占用CPU的百分比
21%sys – 内核空间占用CPU的百分比
766%idle – 空闲CPU百分比
0%iow – IO等待占用CPU的百分比
4%irq – 硬中断(Hardware IRQ)占用CPU的百分比
1%sirq – 软中断(Software Interrupts)占用CPU的百分比
0%host –
我们可以通过计算得知:7+21+766+4+1=799 约等于800%
cpu的占用率(使用率)可以通过 (800%-766%idle)/800%计算得到
PID — 进程id
USER — 进程所有者 ,启动进程的用户。
PR — 进程优先级
NI — nice值。负值表示高优先级,正值表示低优先级
VIRT — 虚拟内存使用量。
RES — 物理内存使用量。
SHR — 共享内存使用量。
S — 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 I=空闲状态
%CPU — 上次更新到现在的CPU时间占用百分比
%MEM — 进程使用的物理内存百分比
TIME+ — 进程占用的CPU时间总计
ARGS— 命令行参数。
Linux proc/目录详解
这里只介绍cpuinfo和stat文件信息
adb shell cat /proc/cpuinfo
主要是cpu的一些硬件信息
processor : 0
Processor : AArch64 Processor rev 4 (aarch64)
model name : AArch64 Processor rev 4 (aarch64)
BogoMIPS : 26.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 1
Processor : AArch64 Processor rev 4 (aarch64)
model name : AArch64 Processor rev 4 (aarch64)
BogoMIPS : 26.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 2
Processor : AArch64 Processor rev 4 (aarch64)
model name : AArch64 Processor rev 4 (aarch64)
BogoMIPS : 26.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 3
Processor : AArch64 Processor rev 4 (aarch64)
model name : AArch64 Processor rev 4 (aarch64)
BogoMIPS : 26.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor
:表示 4 核 CPU,id号0-3
Processor
:处理器的架构和版本信息。,处理器架构为 AArch64,版本为 rev 4。
model name
:同样是描述处理器的架构和版本信息,与上一项类似
BogoMIPS
:在系统内核启动时粗略测算的CPU速度(Million Instructions Per Second)
通过一个简单的循环测试计算出来的值。因此,它并不准确地反映了 CPU 的实际性能。
Features
:列出了该处理器支持的一些特性和指令集。处理器支持的特性包括浮点运算(fp)、SIMD 指令集(asimd)、
事件流(evtstrm)、AES 加密指令(aes)、多倍乘(pmull)、SHA-1 加密指令(sha1)、SHA-2 加密指令 (sha2)、CRC32 校验指令(crc32)等
CPU implementer
:表示 CPU 的实现者标识符,0x41 对应的是 ARM 公司。
CPU architecture
:表示 CPU 的架构版本,8 对应的是 ARMv8 架构。
CPU variant
:表示 CPU 的变体标识符。
CPU part
:表示 CPU 的部件标识符。
CPU revision:
表示 CPU 的修订版本号。
adb shell cat /proc/stat
cpu 10482627 403910 10374029 108104397 17890 2916045 559432 0 0 0
cpu0 1639634 106156 2203923 46409477 14139 527023 133383 0 0 0
cpu1 1593605 91112 2254611 8611648 1234 508073 130478 0 0 0
cpu2 1617916 87120 2244413 8607307 1138 515380 138253 0 0 0
cpu3 1627092 85860 2264758 8598776 1227 511266 142722 0 0 0
cpu4 968015 7045 294983 8974688 30 211232 4194 0 0 0
cpu5 992425 8100 341480 8972072 56 212606 3505 0 0 0
cpu6 1014721 9074 362541 8959730 22 214518 3418 0 0 0
cpu7 1029216 9439 407315 8970693 40 215944 3476 0 0 0
intr 835312893 0 0 3607787 0 0 308627600 0 23601166 0 0 0 0 0 0 0 0 194936 0 0 0 16972073 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 480 3 0 0 11 11 2204672 208308 0 2 1 1838 55 2 204478 0 0 0 0 0 0 2 0 0 0 0 434607 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2449420 0 155234 1898 97723 412499 0 0 69 0 0 0 0 0 2 3 0 0 2 0 11 0 9 429 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 177903 997637 792069 6 199483 2569606 166236 0 0 0 0 0 536208 70822 1878629 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 1 0 1 0 228 0 0 0 6140 19060772 0 1165 0 0 32423 0 0 0 0 0 0 6345 5077 1 2298 0 0 0 0 0 0 0 0 0 0 0 0 0 1099 0 0 2 0 0 0 0 0 12 36 21 948 43 0 41 1394 14 0 63 0 0 43 0 0 52244 6512 0 6039 0 0 44 0 0 0 0 0 345 1416756 0 0 1 33770 0 0
ctxt 1450309488
btime 1701832878
processes 5287756
procs_running 1
procs_blocked 0
softirq 115697955 40856 42519104 155619 819646 504315 0 5772282 35412329 0 30473804
cpu-cpu7 这一段每一列的具体含义如下:
user:CPU 处于进程为用户态的时间。一般/高优先级,仅统计nice<=0
nice:CPU 处于进程为nice用户态的时间。 低优先级,仅统计nice>0
system:CPU 处于内核态的时间。
idle:CPU 处于空闲态的时间。
iowait:CPU 等待 I/O 操作的时间。
IRQ:CPU 处理硬中断的时间。
softIRQ:CPU 处理软中断的时间。
steal:CPU 被其他虚拟 CPU 窃取的时间。
guest:运行虚拟 CPU 时花费真实 CPU 的时间。
guest_nice:运行一个带nice值的guest花费的时间。
即不只是运行虚拟cpu,而且这个cpu的进程优先级较低。
它们的数值单位都为jiffies
看下jiffies的基本定义:
在 Linux 内核中,jiffies 是一个全局变量,用于表示系统启动以来的时钟中断次数。
比如时钟频率为 1000HZ,即每秒发生 1000 次时钟中断,因此 jiffies 值每秒增加 1000,那么1个jiffies=1/1000=0.001s=1ms
标红的两段针对nice值进行了区分,有必要先看下nice的定义:
在 Linux 系统中,nice 值是用来表示进程调度优先级的一个参数,其取值范围是 -20 到 19。nice 值越低,进程的优先级越高,越容易获得 CPU 时间。nice 值越高,进程的优先级越低,CPU 时间分配更少。
具体来说,nice 值的取值范围如下:
- -20:最高优先级
- -19 到 -1:较高优先级
- 0:默认优先级
- 1 到 19:较低优先级
- 20:最低优先级(实际上,nice 值不能超过 19)
中断信息
intr 835312893 0 0 3607787 0 0 30862........
这行给出中断的信息,第一个为自系统启动以来,发生的所有中断的次数,之后的每个数对应一个特定的中断自系统启动以来所发生的次数
上下文切换信息
ctxt 1450309488
自系统启动以来CPU发生的上下文交换的次数
运行时间
btime 1701832878
系统启动时间,以 Unix 时间戳的形式表示。
Unix 时间戳是指自 1970 年 1 月 1 日 00:00:00 UTC 起至当前时间的总秒数。因此,btime 中的时间戳单位是秒。
所有任务信息
processes 5287756
表示自系统启动以来所创建的任务的数量
运行任务信息:
procs_running 1
表示当前运行队列中正在运行着的任务数量
阻塞任务信息
procs_blocked 0
表示当前被阻塞的任务的数量
软中断信息
softirq 115697955 40856 42519104 155619 819646 504315 0 5772282 35412329 0 30473804
表示从系统启动以来的软中断计数,第一列表示所有软中断的总和,之后各列表示某个指定软中断的数量
通过读取、计算 proc/stat下的部分信息来计算当前的cpu占用率
核心思路:1-(idle的jiffies/总的jiffies) *100%
将空闲态占用时间去掉,剩下的不就全是cpu使用的时间了嘛
/**
* ^ 表示匹配行的开头。
* cpu 匹配 "cpu" 这个单词。
* \\s+ 匹配一个或多个空格字符。
* (\\d+\\s+){9} 匹配由一个或多个数字加上一个或多个空格字符组成的序列,重复9次。
* \\d+ 匹配一个或多个数字。
* $ 匹配行的结尾。 因此,整个正则表达式可以匹配以 "cpu" 开头,后面跟着10个由空格分隔的数字的行。
*/
public static String getCPURate() {
String path = "/proc/stat";// 系统CPU信息文件
long Totaljiffies[] = new long[2];
long totalIdle[] = new long[2];
FileReader fileReader = null;
BufferedReader bufferedReader = null;
Pattern pattern = Pattern.compile("^cpu\\s+(\\d+\\s+){9}\\d+$", Pattern.MULTILINE);
//正则表达式,只获取第一行
for (int i = 0; i < 2; i++) { //每一次调用分为两次获取 方便求差
Totaljiffies[i] = 0;
totalIdle[i] = 0;
try {
fileReader = new FileReader(path);
bufferedReader = new BufferedReader(fileReader, 8192);
String str;
while ((str = bufferedReader.readLine()) != null) { //读取stat信息
if (str.toLowerCase().startsWith("cpu")) {//以cpu开头的
Matcher matcher = pattern.matcher(str);//直接获取第一行cpu开头的数据
// 不需要cpu0-7的,那样的话还得多几步运算
while (matcher.find()) {
String[] values = extractValues(matcher.group());
Totaljiffies[i] = sumValues(values);
totalIdle[i] = Long.parseLong(values[3]);
}
}
if(i==0){//第一次获取后进行延时等待系统更新信息
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
double rate = 0;
if (Totaljiffies[1] > Totaljiffies[0] ) {//正常情况下第二次总的jiffies一定比第一次获得的数据大
rate = 1.0 * ((Totaljiffies[1] - totalIdle[1]) - (Totaljiffies[0] - totalIdle[0]))
/ (Totaljiffies[1] - Totaljiffies[0]);
}
return String.valueOf(rate);
}
/**
* 头行去掉cpu,合并成String[]数组
* @param input
* @return
*/
public static String[] extractValues(String input) {
String[] parts = input.split("\\s+");
String[] values = new String[parts.length - 1]; // 去掉 "cpu",所以长度减一
System.arraycopy(parts, 1, values, 0, parts.length - 1);
return values;
}
/**
* 求数组和
* @param input
* @return
*/
public static Long sumValues(String input[]) {
Long sum = Long.valueOf(0);
for (String value : input) {
sum += Integer.parseInt(value);
}
return sum;
}
Oncreate里使用匿名线程更新view,很不严谨···
DecimalFormat df = new DecimalFormat("#0.00");
new Thread() {
@Override
public void run() {
super.run();
while (true) {
cpu = Double.parseDouble(df.format(Double.parseDouble(getCPURate()) * 100));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Cpurate.setText("cpu占用率为"+String.valueOf(cpu)+"%");
}
}
}.start();
对比top:
注:需要将Selinux权限设置为宽容模式,不然没有权限读取内部信息:adb shell setenforce 0
因为时间更新的缘故,top显示的比我app上的更新的快一点。
本文归纳了查看Android上cpu大部分信息的方法以及java上层获取计算cpu使用率的方法,希望对你有所帮助。