Linux下从CPU/内存/IO三个方面来分析系统性能,HOOK和crash开源项目

文章介绍了sysstat工具包在监控系统性能中的作用,包括CPU、内存和IO的利用率,并详细阐述了如何通过工具分析系统平均负载、CPU使用率和IO瓶颈。此外,针对Android系统,文章提供了性能分析和崩溃排查的方法,如使用adb命令和logcat进行问题定位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在实际生产环境中是否遇到如下问题?
系统平均负载过高。
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性能下降

四.安卓系统性能分析总结

五.安卓系统崩溃分析

5.1 adb logcat 崩溃分析

5.2 adb bugreport

5.2 性能分析网页程序

五. hook技术总结

六. crash捕获


一.sysstat软件包

        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

三.性能问题的常见情况


3.1 查看OS的日志

比如/var/log/messages里面是否有error,fail,warn等信息

3.2 查看系统平均负载 

        使用uptime查看系统平均负载,从这个命令的load average可以知道系统最近 1 分钟、5 分钟、15 分钟的系统平均负载。系统平均负载指的是处于可运行或不可中断状态的平均进程数,理想状态下,每个逻辑CPU运行一个进程,因此例如当前系统的逻辑CPU数量是12,理想状态load average也应该是12,上图的load average是2左右,则表示有CPU处于空闲状态。

3.3 平均负载与CPU利用率

        由于系统平均负载反映的是处于R状态和D状态的进程数,因此不代表CPU的使用率就是高,这两者没有必然的联系。对于计算密集型任务较多的场景来说,系统平均负载的升高意味着CPU使用率上升。但是对于IO密集型任务较多的场景来说,系统平均负载升高时CPU利用率通常都不高,因为有很多进程都处于D状态。
1) 如果系统平均负载率很高同时CPU的使用率也很高,则需要考虑的是系统可能遇到了CPU瓶颈,需要去定位CPU方面的原因。
2) 如果系统平均负载率很高,但是CPU的使用率不高,则需要考虑的是系统可能遇到了IO瓶颈,需要去定位IO方面的原因。

3.4 系统平均负载高同时CPU使用率也高

       需要去定位CPU方面的原因。
1) 首先使用下面的命令查看每一秒的CPU的核心的变化信息:
mpstat -P ALL 1
2) 使用pidstat命令去查看进程占用的CPU情况:
pidstat -u 1

3.5 系统平均负载高但CPU使用率不高

       需要去定位IO方面的原因。
1) 首先使用下面的命令查看每一秒的CPU的核心的变化信息:
mpstat -P ALL 1
可以看到iowait占用比较高
2) 使用sar -d -p 1查看哪个块设备的使用率比较高。
3) 使用pidstat -d 1命令查看具体是哪个进程导致IO升高的。

3.6 由于CPU上下文切换频繁导致系统平均负载升高

        一般每次上下文切换都需要几十纳秒到数微秒的 CPU 时间,如果切换较多还是很容易导致 CPU 时间的浪费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,
这里同样会导致系统平均负载升高。
1) 通过下面的命令查看系统上下文切换:
vmstat 1
2)使用pidstat查看具体的进程上下文切换信息,以判断是哪个。
pidstat -u 1 -w -t
说明大部分sysbench进程都在被强制调度,也就是在争抢CPU资源,说明CPU成为了性能瓶颈。

3.7 内存不足引起的OS性能下降

        可以通过下面的方法去排查:
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

五.安卓系统崩溃分析

5.1 adb logcat 崩溃分析

(1) adb logcat > crash.log

打开crash.log搜索关键字beginning of crash,可以看到崩溃的线程

例如崩溃地址如下:

 (2) 获取崩溃地址

(3)反编译

arm-linux-androideabi-addr2line -C -f -e libMyEngine.so 144ed20

5.2 adb bugreport

(1) adb bugreport 提取崩溃堆栈文件


(2) 解压导出的文件


堆栈文件路径:FS/data/tombstones


(3) 打开墓碑文件关注其中的崩溃原因和调用堆栈

根据修改时间进行确定分析那个文件


(4) 对应的带符号的so,并进入so所在目录
例如:cd output/libs/arm64-v8a
(5) 定位行号
addr2line -C -f -e libMyEngine.so 000000000266bfb0

反编译多个崩溃地址:

aarch64-linux-android-addr2line   -Cfaipe   libMyEngine.so 0000000001064988 0000000001068b3c 0000000001069674 000000000105d08c 000000000108fda0 000000000108b520 000000000108b448 00000000010d368c 00000000010d0dbc

重点说明:实际开发中崩溃后遇到墓碑文件和logcat中都没有堆栈的情况,可尝试通过更换设备进行复现。

5.2 性能分析网页程序

 https://profiler.firefox.com

输入线程名:

选中火焰图或者堆栈看调用树查看详情

五. hook技术总结

Android Native Hook技术路线概述 - GToad Sec Blog

字节跳动bhook项目:PLT hook

https://github.com/bytedance/bhook

字节项目:inline hook

https://github.com/bytedance/android-inline-hook​​​​​​​

爱奇艺APP开源:native PLT hook

(项目说明:https://bbs.kanxue.com/thread-227105.htm

https://github.com/iqiyi/xhook

六. crash捕获

爱奇艺视频 APP 使用的 Android native crash + Java exception 捕获方案:

xCrash 是一个安卓 APP 的崩溃捕获库。它支持捕获 native 崩溃和 Java 异常。

xCrash 能在 App 进程崩溃时,在你指定的目录中生成一个 tombstone 文件(格式与安卓系统的 tombstone 文件类似)。并且,不需要 root 权限或任何系统权限。

xCrash 已经在 爱奇艺 的很多安卓 APP(包括爱奇艺视频)中被使用了很多年。

https://github.com/iqiyi/xCrash​​​​​​​

xCrash说明:

https://bbs.kanxue.com/thread-250716.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值