1、Android性能参数的获取方式包括以下三种来源:
1.1、是Android从linux继承来的特性,与进程相关的信息会保存在文件/proc中,监控工具做的事情就是去读取解析文件;
1.2、是Android系统提供的API,监控工具直接调API再进行相应的处理既可;
1.3、是从Android命令中获取需要的数据,监控工具先采用Runtime调用命令获取命令返回值进而解析处理得到需要的数据。
下文分别针对常见的几种数据获取原理进行介绍。
2、PID/UID概念及获取
上面提到的三种方法,前两个都需要有一个参数,有了这个参数,才能把数据文件和应用对应起来,这个参数通常是PID或者UID。
说到PID,UID,这里简单介绍一下,与linux、windows一样,Android中PID标识的也是进程号,其实一个Android应用可以是单进程,也可以是多个进程,多进程时一个App则对应多个PID,且App退出(进程销毁)再打开后进程号通常会被系统重新分配。UID与PID不同,UID与Android应用是一一对应的,是应用的身份标识,UID是App安装后固定不变的。
PID的获取其实并没有非常直接的API(比如根据App包名查询到),通常是采用曲线的方式,Android中可以获取所有当前运行的App应用进程,通过遍历查询这些进程的包名信息是否与被监控的App包名信息一致,来得到App的当前运行进程。
获取进程后即可通过查询该进程信息的属性得到PID,UID也可以通过相同方法获得。当然如果这个App当前并没有在运行,那么PID则获取不到。但是当App不在运行的时候,UID的获取可以直接使用API获取得到。
有了PID和UID,可以开始讨论其他数据的获取原理了。
3、/proc文件
/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。
由于系统的信息,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。 从proc文件中我们可以获取cup、内存等实时信息。
4、cpu信息获取
4.1、进程cpu数据
进程CPU数据是根据PID通过读取系统文件(/proc/PID/stat)得到。读取文件后,根据该文件参数定义挑选出该进程使用的CPU时间,以百度外卖app为例,如下图。重点关注每行中的第14~17个数据,这四个值分别是utime,stime,cutime,cstime。其含义为:
utime,进程在用户代码执行的累积时间,单位为jiffies
stime, 进程在内核代码执行的累积时间,单位为jiffies
cutime,进程在用户代码等待线程执行的累积时间,单位为jiffies
cstime,进程在内核代码等待线程执行的累积时间,单位为jiffies
进程的总Cpu时间processCpuTime = utime + stime + cutime + cstime
4.2、进程cpu占用率
注意,上面说到四个值都是累积值,既然是累积值,如果想得到CPU的瞬时值,则需要取到A时刻和B时刻的CPUTime值,相减即得到A时刻到B时刻该进程增加的CPUTime,最后只要除以A时刻到B时刻整体cpu增加的CPUTime即得到该进程的CPU占用率 了。
CPU占用率 = (进程CPUTime2-进程CPUTime1)/(系统CPUTime2-系统CPUTime1) 。
4.3、整体cpu占用率
整体cpu占用数据可以通过读取系统文件/proc/stat得到,如下图。看第一行到第五行,cpu代表整体的cpu数据,cpu0-cpu3代表手机每个cpu的数据,从图中可以看出,我们使用的测试手机是四核。以第一行数据为例,cpu后面各个数值的含义如下
user 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。
nice 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system 从系统启动开始累计到当前时刻,处于核心态的运行时间
idle 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间
iowait 从系统启动开始累计到当前时刻,IO等待时间
irq 从系统启动开始累计到当前时刻,硬中断时间
softirq 从系统启动开始累计到当前时刻,软中断时间
总的cpu时间totalCpuTime = user + nice + system + idle + iowait + irq + softirq
其中,第4个数值代表系统开机后累积的空闲值,A时刻到B时刻消耗的cpu时间则可以通过B时刻的开机累积时间减去A时刻的开机累积时间得到。利用空闲值则可以得到从A时刻到B时刻的整体CPU占用率。
5、内存
5.1、进程内存
安卓内存占用可用以下四个概念作为衡量
VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
对于进程内存的获取不需要读取/proc文件,也没有像CPUTime存在累积的概念,安卓系统给我们提供了获取进程占用内存的API。只需要将进程的PID作为参数传递给相应API即可获取到,代码如下,通常我们采用USS做为衡量标准。
public int getPidMemorySize(int pid, Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int[] myMempid = new int[] { pid };
Debug.MemoryInfo[] memoryInfo = am.getProcessMemoryInfo(myMempid);
memoryInfo[0].getTotalSharedDirty();
// int memSize = memoryInfo[0].getTotalPss();
int memSize = memoryInfo[0].getTotalPrivateDirty();
return memSize;
}
5.2、系统总内存/剩余内存
6 、流量数据
流量数据的获取是通过UID。有两种获取方式:1、安卓系统提供的API;2、读取"/proc/uid_stat/" + uid + "/tcp_rcv"和/proc/uid_stat/" + uid + "/tcp_snd"文件。其中API获取方式如下图:
rcvTraffic = TrafficStats.getUidRxBytes(Integer.parseInt(uid));
sndTraffic = TrafficStats.getUidTxBytes(Integer.parseInt(uid));
网友评论