安卓cpu信息查看与cpu占用率计算

avatar
作者
猴君
阅读量:0

文章目录

前言

通过查看系统cpu信息可以监控系统的程序运行状况以及系统状况,对后续的性能优化、故障诊断、资源管理、安全性等等都非常重要。
众所周知安卓基于Linux,查看cpu相关信息的方法基本相同,但是部分参数与linux略有区别,这里只针对安卓上的部分参数作基本解读


一、Android查看cpu相关信息的方法

1.1 Top命令

adb shell top 或adb shell Enter(回车) top

在这里插入图片描述

1.1.1 任务总览

任务(进程) 系统现在共有592个进程,其中处于运行中的有2个,590个在休眠(sleep),stoped状态的有0个,zombie状态(僵尸)的有0个

1.1.2 内存使用

内存状态: 物理内存总量 (3.5G) 使用中的内存总量(3.4G) 空闲内存总量(59Mb) 缓存的内存量(15Mb)
1TB=1024GB ,1GB=1024MB ,1MB=1024KB ,1KB=1024字节。

1.1.3 交换区状况

swap交换分区: 交换区总量(2.0G) 使用的交换区总量(98Mb) 空闲交换区总量(1.9G) 缓冲的交换区总量(1.4G)

1.1.4 cpu占用率

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%计算得到

1.1.5 进程详细信息

PID — 进程id
USER — 进程所有者 ,启动进程的用户。
PR — 进程优先级
NI — nice值。负值表示高优先级,正值表示低优先级
VIRT — 虚拟内存使用量。
RES — 物理内存使用量。
SHR — 共享内存使用量。
S — 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 I=空闲状态
%CPU — 上次更新到现在的CPU时间占用百分比
%MEM — 进程使用的物理内存百分比
TIME+ — 进程占用的CPU时间总计
ARGS— 命令行参数。

1.2 proc/xxx 目录

Linux proc/目录详解

这里只介绍cpuinfo和stat文件信息

1.2.1 cat /proc/cpuinfo

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 的修订版本号。

1.2.2 cat /proc/stat

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 
1.2.2.1 cpu信息总览

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)
1.2.2.2中断信息
intr 835312893 0 0 3607787 0 0 30862........ 

这行给出中断的信息,第一个为自系统启动以来,发生的所有中断的次数,之后的每个数对应一个特定的中断自系统启动以来所发生的次数

1.2.2.3 上下文切换信息
ctxt 1450309488 

自系统启动以来CPU发生的上下文交换的次数

1.2.2.4 运行时间
btime 1701832878 

系统启动时间,以 Unix 时间戳的形式表示。
Unix 时间戳是指自 1970 年 1 月 1 日 00:00:00 UTC 起至当前时间的总秒数。因此,btime 中的时间戳单位是秒。

1.2.2.5 所有任务信息
processes 5287756 

表示自系统启动以来所创建的任务的数量

1.2.2.6 运行任务信息:
procs_running 1 

表示当前运行队列中正在运行着的任务数量

1.2.2.7 阻塞任务信息
procs_blocked 0 

表示当前被阻塞的任务的数量

1.2.2.8 软中断信息
softirq 115697955 40856 42519104 155619 819646 504315 0 5772282 35412329 0 30473804 

表示从系统启动以来的软中断计数,第一列表示所有软中断的总和,之后各列表示某个指定软中断的数量


二、cpu占用率的计算

通过读取、计算 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使用率的方法,希望对你有所帮助。

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!