How to get performance data in Android

本文记录下在Android平台上如何获取那些系统性能相关的数据。

1. CPU平均负载

读取文件节点/proc/loadavg,分别是1min/5min/15min内CPU的负载情况。 读取方式的代码示例:

private static final int[] LOAD_AVERAGE_FORMAT = new int[]{
       PROC_SPACE_TERM | PROC_OUT_FLOAT,                 // 0: 1 min
       PROC_SPACE_TERM | PROC_OUT_FLOAT,                 // 1: 5 mins
       PROC_SPACE_TERM | PROC_OUT_FLOAT                  // 2: 15 mins
};

public float mLoad1 = 0;
public float mLoad5 = 0;
public float mLoad15 = 0;
private final float[] mLoadAverageData = new float[3];

private void getLoadAverage() {
   final float[] loadAverages = mLoadAverageData;
   if (Process.readProcFile(FILE_PORC_LOAD, LOAD_AVERAGE_FORMAT, null, null, loadAverages)) {
       float load1 = loadAverages[0];
       float load5 = loadAverages[1];
       float load15 = loadAverages[2];
       if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {
           mLoad1 = load1;
           mLoad5 = load5;
           mLoad15 = load15;
       }
   }
}
2. CPU的频率

CPU的核数:统计 /sys/devices/system/cpu/ 目录下名称以cpu开始的文件夹的数目 正在工作的核: /sys/devices/system/cpu/online 注意:可能是1-4或者2,3或者1-3,5-7等各种组合形式 正在工作的核的频率,例如cpu0的频率节点: /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

3. 内存碎片化程度

文件节点:/sys/kernel/debug/extfrag/unusable_index

$ cat /sys/kernel/debug/extfrag/unusable_index                      
Node 0, zone      DMA 0.000 0.802 0.894 0.971 0.985 0.995 1.000 1.000 1.000 1.000 1.000
Node 0, zone  Movable 0.000 0.000 0.000 0.000 0.002 0.003 0.003 0.003 0.004 0.006 0.006

(1)zone的个数不确定,名称也不确定 (2)先计算单个zone的平均值,再计算zone的整体平均内存碎片化程度

参考资料:https://chengyihe.wordpress.com/2015/11/28/kernel-mm-syskerneldebugextfragunusable_index/

4. 虚拟内存信息

vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写, 是实时系统监控工具。vmstat结果中r,b,in,cs是通过 /proc/stat 文件计算得到的,si,so,bi,bo是通过 /proc/vmstat 文件计算得到的。

需要注意的是,/proc/vmstat 文件中 pgpgin,pgpgout,pswpin,pswpout等值的单位是page,而vmstat命令返回的结果的单位是kb,所以需要进行单位转换,一般情况下,一页的大小是4KB。除此之外,时间间隔是从/proc/uptime中读取计算出的差值,该文件中保存的是系统从启动到当前时刻的时间,单位是秒。

关于中断in:vmstat命令的返回的in值指的是CPU在软中断上占用的时间差值,而不是中断数的差值。如果计算后者的话,可以从/proc/stat的intr中读取从系统启动到当前时刻总共发生的中断数来计算差值。

参考资料:vmstat命令详解

5. 内存信息

文件节点:/proc/meminfo,统计得到total, used, free, cached, buffers, active, inactive, swap total, swap free

$ cat /proc/meminfo
MemTotal:        2808452 kB
MemFree:          535824 kB
MemAvailable:     775404 kB
Buffers:           21840 kB
Cached:           302588 kB
SwapCached:        18792 kB
Active:           668900 kB
Inactive:         313524 kB
Active(anon):     511716 kB
Inactive(anon):   169452 kB
Active(file):     157184 kB
Inactive(file):   144072 kB
Unevictable:        4176 kB
Mlocked:               0 kB
SwapTotal:       1404224 kB
SwapFree:        1153856 kB
Dirty:                 4 kB

1.swap cached 不等于 swap used, swap used = swap total - swap free 2.Memory Free = MemFree + Cached + Buffers 3.Memory Used = Memory Total - Memory Free

参考资料:linux内存管理原理 buffers和cached的区别 active和inactive的区别

6. CPU被占用的情况

CPU被占用的时间比数据的文件节点:/proc/stat

$ cat /proc/stat
cpu  229649 59778 316872 3688440 3308 6 357 0 0 0
cpu0 111250 7718 210302 3466017 764 6 209 0 0 0

jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数。在linux中,一个节拍大致可理解为操作系统进程调度的最小时间片,不同linux内核可能值有不同,通常在1ms到10ms之间。

user (229649) 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies),不包含nice值为负的进程 nice (59778) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies) system (316872) 从系统启动开始累计到当前时刻,核心系统进程占用的时间(单位:jiffies) idle (3688440) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies) iowait (3308) 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) irq (6) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies) softirq (357) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)

上面结果中的后面三个数据在Android中不统计,所以 total = user + nice + system + idle + iowait + irq + softirq 百分比的计算方式一般是: USER%=(user+nice)/total,SYS%=system/total,IOW%=iowait/total,IRQ%=(irq+softirq)/total

参考资料:cpu被占用的时间比信息详解

7. 进程/线程的占用信息

进程数据文件的节点: /proc/[pid] 线程数据文件的节点: /proc/[pid]/task/[tid]

进程和线程的状态信息从stat文件中获取,名称从cmdline文件中获取,cpuset从cpuset文件中获取等。进程的stat文件中保存了该进程的user timesystem time,两者之和可以用来对进程进行排序,一般进程和线程的排序方式都是按照它们占用的CPU时长来排序的。

(1)Process.getPids方法既可以用来获取某个目录下的所有进程数组,也可以用来获取某个进程的task目录下的所有线程数组 (2)Process.getPss方法可以用来统计进程的pss数据,但是很多进程的pss数据都没法获取到

参考资料:关于/proc/pid/stat

进程和线程部分的实现相对有点难度,一方面要统计系统所有的进程和线程的信息,另一方面要对它们进行排序。不过庆幸的是Android系统源码中有一个LoadAverageService,这个service也就是开发者选项中显示CPU使用情况的内部实现,它的代码非常具有参考价值,我们可以在它的基础上进行扩展开发自己的工具。

上面只是列举了部分常见的重要数据的获取方法,其他数据的获取方式也都差不多,主要是要知道当前平台的相应数据的文件节点,还需要注意的是是否具有文件的读权限。

下图是我最近开发的悟空监视器,入口在Flyme系统的开发者选项中(公司内部项目,源码不能公开,仅供参考,原理同上)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏李家的小酒馆

Hiberante知识点梳理

Hibernate简介 Hibernat是一个ORM(关系映射)框架,对JDBC访问数据库的操作进行了简化,并且将数据库表中的字段和关系映射为对象,简化了对数据...

1990
来自专栏ascii0x03的安全笔记

PHP防止SQL注入的方法

菜鸟今天刚刚学习PHP和SQL方面的内容,感觉坑比较深,做一下简单的记录,欢迎批评交流。 主要有两种思路一种是过滤,一种是使用占位符,据说第二种可以根本解决SQ...

38810
来自专栏技术之路

go微服务框架go-micro深度学习(一) 整体架构介绍

      产品嘴里的一个小项目,从立项到开发上线,随着时间和需求的不断激增,会越来越复杂,变成一个大项目,如果前期项目架构没设计的不好,代码会越来越臃肿,难以...

1.5K3
来自专栏difcareer的技术笔记

Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)[转]include <stdio.h>int func(int a, int b, int c, int d, int e,

声明:本文转自Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码),此文干货很多。

5285
来自专栏CSDN技术头条

一组 Redis 实际应用中的异常场景及其根因分析和解决方案

在上一场 Chat《基于 Redis 的分布式缓存实现方案及可靠性加固策略》中,我已经较为全面的介绍了 Redis 的原理和分布式缓存方案。如果只是从“会用”的...

3623
来自专栏大内老A

[WCF安全系列]谈谈WCF的客户端认证[用户名/密码认证]

对于基于Internet的应用,基于用户名和密码的认证方式是最为常用的,而WCF为你提供了不同模式的用户名认证方式。首先还是从用户凭证的表示说起。 一、用户名/...

2279
来自专栏张善友的专栏

分布式文件存储的数据库开源项目MongoDB

MongoDB是一个基于分布式文件存储的数据库开源项目。由C++语言编写。旨在为WEB应用提供可护展的高性能数据存储解决方案。 它的特点是高性能、易部署、易使用...

3509
来自专栏葡萄城控件技术团队

Winform文件下载之WinINet

在C#中,除了webclient我们还可以使用一组WindowsAPI来完成下载任务。这就是Windows Internet,简称 WinINet。本文通过一个...

2218
来自专栏菩提树下的杨过

mybatis 3.x 缓存Cache的使用

mybatis 3.x 已经支持cache功能了,使用很简单,在mappper的xml文件里添加以下节点: 1 <mapper namespace="com....

22710
来自专栏Ken的杂谈

基于GitLab的Code Review教程

也就是说,使用GitLab进行Code Review就是在分支合并环节发起Merge Request,然后Code Review完成后将代码合并到目标分支。

1.3K3

扫码关注云+社区

领取腾讯云代金券