在实际生产环境中是否遇到如下问题?
系统平均负载过高。
CPU使用率过高。
硬盘利用率已经饱和,IO存在瓶颈。
首先明确一下进程的常见6种状态
R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列。
S睡眠状态(sleeping)
D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped)
Z僵尸状态(Zombies)
X死亡状态(dead)
目录
一.sysstat软件包
二.性能分析常用工具
三.性能问题的常见情况
3.1 查看OS的日志
3.2 查看系统平均负载
3.3 平均负载与CPU利用率
3.4 系统平均负载高同时CPU使用率也高
3.5 系统平均负载高但CPU使用率不高
3.6 由于CPU上下文切换频繁导致系统平均负载升高
3.7 内存不足引起的OS性能下降
四.安卓系统性能分析总结
sysstat软件包是一组包含监测系统性能及效率的工具套件,这些工具用于我们收集系统性能数据。比如CPU使用率、硬盘和网络吞吐数据,这些数据的收集和分析,有利于我们判断系统是否正常运行,是提高系统运行效率、安全运行服务器的得力助手。sysstat软件包一般包含如下工具:
sar
iostat
sa1
sa2
sadf
mpstat
sadc
sysstat
sysstat工具包包含两类工具:
即时查看工具:iostat mpstat sar
累计统计工具:sar
sar 具有这两种功能。因此,sar 是 sysstat 中的核心工具。sar(System Activity Reporter)是系统活动情况报告的缩写。
这些命令有的是服务,有的是查看结果的命令。也有的是即时服务器CPU,内存以及网络的使用率
比如先要打开sa1 sa2或者sysstat 才能使用sar sadf sadc
还有即时服务器的CPU,内存,网络使用率的命令,比如:mpstat iostat
为了实现sar的累计统计,系统必须周期地记录当时的信息,这是通过调用如下三个工具实现的:
sa1: 收集并存储每天系统动态信息到一个二进制的文件中,用作 sadc 的前端程序
sa2: 收集每天的系统活跃信息写入总结性的报告,用作 sar 的前端程序
sadc: 系统动态数据收集工具,收集的数据被写入一个二进制的文件中,它被用作 sar 工具的后端
工具具体使用可参考:http://www.ctohome.com/FuWuQi/1b/688.html
安装
1.命令行安装
sudo apt install sysstat
2.源码编译安装
1)源码下载
http://perso.wanadoo.fr/sebastien.godard/ 下载最新的版本源码包,比如我下载的是sysstat-5.1.1.tar.gz
2)解包:
ar zxvf sysstat-5.1.1.tar.gz
3)编译安装
cd sysstat-5.1.1
make config
这个命令就是用来配置sysstat安装的,如果不用这个命令,可以直接安装到其默认的/usr/local/lib目录中
make
make install
CPU利用率:top,mpstat,sar -w, vmstat
内存利用率:free
IO吞吐率:throughput, iops, iostat -x
比如/var/log/messages里面是否有error,fail,warn等信息
使用uptime查看系统平均负载,从这个命令的load average可以知道系统最近 1 分钟、5 分钟、15 分钟的系统平均负载。系统平均负载指的是处于可运行或不可中断状态的平均进程数,理想状态下,每个逻辑CPU运行一个进程,因此例如当前系统的逻辑CPU数量是12,理想状态load average也应该是12,上图的load average是2左右,则表示有CPU处于空闲状态。
由于系统平均负载反映的是处于R状态和D状态的进程数,因此不代表CPU的使用率就是高,这两者没有必然的联系。对于计算密集型任务较多的场景来说,系统平均负载的升高意味着CPU使用率上升。但是对于IO密集型任务较多的场景来说,系统平均负载升高时CPU利用率通常都不高,因为有很多进程都处于D状态。
1) 如果系统平均负载率很高同时CPU的使用率也很高,则需要考虑的是系统可能遇到了CPU瓶颈,需要去定位CPU方面的原因。
2) 如果系统平均负载率很高,但是CPU的使用率不高,则需要考虑的是系统可能遇到了IO瓶颈,需要去定位IO方面的原因。
需要去定位CPU方面的原因。
1) 首先使用下面的命令查看每一秒的CPU的核心的变化信息:
mpstat -P ALL 1
2) 使用pidstat命令去查看进程占用的CPU情况:
pidstat -u 1
需要去定位IO方面的原因。
1) 首先使用下面的命令查看每一秒的CPU的核心的变化信息:
mpstat -P ALL 1
可以看到iowait占用比较高
2) 使用sar -d -p 1查看哪个块设备的使用率比较高。
3) 使用pidstat -d 1命令查看具体是哪个进程导致IO升高的。
一般每次上下文切换都需要几十纳秒到数微秒的 CPU 时间,如果切换较多还是很容易导致 CPU 时间的浪费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,
这里同样会导致系统平均负载升高。
1) 通过下面的命令查看系统上下文切换:
vmstat 1
2)使用pidstat查看具体的进程上下文切换信息,以判断是哪个。
pidstat -u 1 -w -t
说明大部分sysbench进程都在被强制调度,也就是在争抢CPU资源,说明CPU成为了性能瓶颈。
可以通过下面的方法去排查:
1) 首先查看dmesg日志,查看是否有Out of memory打印,如果有,说明有程序在申请内存时失败,内存不足,这种情况有可能由两种原因引起。一是物理内存不足,二是内存碎片化严重,导致后面的程序申请大片连续内存时无法分配成功。
2) 通过sar -r 1命令去查看当前的内存的使用率,主要看%memused,如果使用率超过了90%,说明物理内存已经不足。
3) 通过sar -W 1命令查看交换分区的活动,如果pswpin/s和pswpout/s的值比较高,说明物理内存已经不足,正常这个值是0。
4) 通过vmstat -a命令中的swpd查看交换分区使用的大小,以此进一步判断物理内存是否已经不足。
5) 通过pidstat -r 1命令查看%MEM域,查看哪些进程占用的内存过多。
安卓系统也是基于Linux内核的,关于其性能分析常用总结如下:
1)查找进程名称 adb shell ps -ef | grep com.test.xuexi
21332 u0_a290 10 -10 1.6G 345M 189M S 15.3 6.0 2:42.39 com.test.xuexi
21578 u0_a290 20 0 1.1G 100M 82M S 0.6 1.7 0:05.89 com.test.xuexi:remote
2)分析对应进程线程CPU和内存消耗
adb shell top -H | grep u0_a290
3)显示所有线程的CPU和内存消耗
adb shell top -H
4)查找进程21332下的所有线程CPU和内存消耗
adb shell top -H -p 21332
5) 进入adb shell统计进程信息
adb shell
top | grep com.test.xuexi | grep -v shell
6) top -d -n
-b:查找所有(top默认按照cpu消耗排序且只会展示一屏的信息,-b表示要展示所有的进程信息)
-d:刷新的时间间隔,默认是5秒
-n:指定刷新次数
7) 命令行参数
-d 1 -n 300 -n-long 8000 -device-id 00000000112da443 -package-name com.test.xuexi -launch-activity .NaviAutoActivity -os-version 8.0 -seed 200 -throttle 500 -time 20000 -onlymonkey 0
8)启动weditor来定位安卓界面元素
python -m weditor
9) 枚举设备
adb devices
例如得到:HA1FRPDH
10)top查看指定设备性能信息
adb -s HA1FRPDH shell top
11)dumpsys查看指定设备cpu消耗
adb -s HA1FRPDH dumpsys cpuinfo
12)adb install 常用命令行参数说明
-r :覆盖安装
-l :锁定应用程序
-t :允许测试包
-d :允许降级覆盖安装
-p :部分应用安装
-g :为应用程序授予所有运行时的权限
13)top vs dumpsys使用举例
adb shell dumpsys meminfo com.test.xuexi
adb shell dumpsys cpuinfo | grep com.test.xuexi
adb shell top -b -n 1 | grep com.test.xuexi
14)dumpsys使用
Android程序内存被分为2部分:native和dalvik,dalvik就是我们平常说的java堆,我们创建的对象是在这里面分配的。
dumpsys能做的事还有很多 dumpsys [options] -meminfo 显示内存信息 -cpuinfo 显示CPU信息 -account 显示accounts信息 -activity 显示所有的activities的信息 -window 显示键盘,窗口和它们的关系 -wifi 显示wifi信息
15)VSS,RSS ,PSS ,USS
VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
16) dumpsys统计app性能参数自动化脚本
#!/bin/bash
starttime=`date "+%Y-%m-%d_%H-%M-%S"`
dirname=testmem_$starttime
mkdir $dirname
cd $dirname
mkdir meminfo
echo "Time,TOTAL,Java,Native,Code,Stack,Graphics,Other,System" > mem.csv
#exit 0
while true
do
datetime=`date "+%Y-%m-%d_%H-%M-%S"`
filename=meminfo/${datetime}.txt
pid=`adb shell pidof com.test.xuexi`
adb shell dumpsys meminfo $pid > ${filename}
Java=`cat ${filename}|grep "Java Heap:"|awk '{print $3}'`
Native=`cat ${filename}|grep "Native Heap:"|awk '{print $3}'`
Code=`cat ${filename}|grep "Code:"|awk '{print $2}'`
Stack=`cat ${filename}|grep "Stack:"|awk '{print $2}'`
Graphics=`cat ${filename}|grep "Graphics:"|awk '{print $2}'`
Other=`cat ${filename}|grep "Private Other:"|awk '{print $3}'`
System=`cat ${filename}|grep "System:"|awk '{print $2}'`
TOTAL=`cat ${filename}|grep "TOTAL:"|awk '{print $2}'`
echo "$datetime,$TOTAL,$Java,$Native,$Code,$Stack,$Graphics,$Other,$System"
echo "$datetime,$TOTAL,$Java,$Native,$Code,$Stack,$Graphics,$Other,$System" >> mem.csv
sleep 1
done
17) grep过滤重定向
adb shell top -b -d 1 | grep 30286 --line-buffered > result.txt
18) 采集1000个点
adb shell top -b -n 1000 -d 1 | grep --line-buffered com.test.xuexi
adb shell top -b -n 1000 -d 1 | grep --line-buffered 22036