一个获取 Android 某个 package 的 CPU 占用率,内存占用率,系统 IOPS .. 程序
本文是作者结合自己的开发经验,参考 Linux 官方文档,和其他的一些 Android 文档编辑而成,但因开发此 脚本的时候并没有记录参考资料,如果在此文没有指出出去的地方,在此深表歉意。
我认为,代码是最能说明功用的手段,除非代码写得太复杂,或者太乱。因此我不会再额外说明脚本中处理流程。 但此脚本中几个注意的点,我会事先说明。
首先该脚本依赖 adb, 因为作者本意是通过此脚本去获取 Android APK 的各项参数。 而 Android 系统一般会自带 adb, 而且更具系统的不同您可能要处理权限方面的问题。 但是该脚本可以轻松的换成 ssh 去采集也是可以的。而为什么采用 Shell 而不是用 Python, Node.js, Go 编写采集程序,主要是因为这样开发效率更高,但是在某些 Windows 机器上 shell 的执行效率比较底下(比如说跑在 4 代或者 5 代 i3 win10),此时最好换成 ssh 和更高效的语言去实现。,但基本采集数据的思想都是相同的。
因为效率原因后面将该脚本换成了从系统内部执行,adb 部分删除了。
脚本采集的参数有 CPU 占用率,内存消耗,整体 IO 的消耗,线程数。 下面我会具体的说明各个参数是如何采集的。
另外一般 Linux 里面表示 CPU 占用率表示的是单颗 CPU 的占用率,如果硬件有超过一颗 CPU (虚拟的也算)那么总的 CPU 占用率会超过 100%, 比如说 4 核的 CPU 占用率是 400%。 而此脚本中计算的 CPU 为每秒占总 CPU 的占比,因此恒定为 100%。但如果想要换成通用的计算标准,在最后不去平均核数即可。
为了美化打印,这里采用了 3/4 bit 的颜色模式,但是可能在某些终端不支持,从而会打印出一些多余的乱码, 此时直接在前面的函数中去掉颜色控制方面的代码即可(换成其他的前导码或者 256 色模式也可以试一试)。
脚本最后会在目标路径生成一个 csv 文件。该脚本还有一个配套的数据统计脚本,脚本时间轴还有些问题先不上传了(后续更新)。
如果想了解更多关于 Proc 相关的信息,请在 Linux 系统下执行 man 5 proc。
如果想了解 /proc/diskstate 相关的信息,请访问 Linux 内核工程中 Documentation/iostats.txt 文档。
#!/system/bin/sh
# set -e
# ------------------------------------------------------------------------------
# Author: mojies
# 使用说明:
# 1. 先将该脚本上传到测试设备
# 2. 给改脚本家可执行权限 chmod +x ./SamplingSysData-xxxxxxxx.sh
# 3. 该脚本采集五个数据
# 1. date 采集时的系统时间
# 2. flash /data/data/${package} 消耗 Flash 大小
# 3. mem 应用启动之后消耗的系统内存
# 4. cpu 应用启动之后在监测点监测到的数学平均 CPU 占用率,单位 1/1000
# 5. iow 系统造成的 iops
# 4. 使用时请运行以下命令采集指定包的运行时数据
# ./SamplingSysData-xxxxxxxx.sh ${package}
# 如:
# ./SamplingSysData-xxxxxxxx.sh com.xxx.xxx
# 5. 生成的数据在 /data/SamplingSysDaya/${package} 目录下用如下命令将采集数据
# 打印到终端
# ls /data/SamplingSysDaya/${package} | while read line; do echo "$line"; cat /data/SamplingSysDaya/${package}/${line}; echo ""; done
#
#
# ------------------------------------------------------------------------------
# -----------------------------------------------------------------------------
echo_red(){
echo -e "\e[1;31m$1\e[0m"
}
echo_yellow(){
echo -e "\e[1;33m$1\e[0m"
}
echo_green(){
echo -e "\e[1;32m$1\e[0m"
}
echo_blue(){
echo -e "\e[1;34m$1\e[0m"
}
echo_purple(){
echo -e "\e[1;35m$1\e[0m"
}
echo_cyan(){
echo -e "\e[1;36m$1\e[0m"
}
function show_help_info(){
echo_green "------------------------------------------------------------"
echo_green "Option:"
echo_green " --pkg | -p 包名"
echo_green " --duration | -d 采样频率"
echo_green " --verbose 是否打印详细信息( 不需要指定参数 )"
echo_green " --result_dir 指定保存采样数据目录"
echo_green "ex:"
echo_green " ./deploy.sh -p com.xxx.xxxx -d 1"
echo_green "------------------------------------------------------------"
exit -1
}
# -----------------------------------------------------------------------------
export PARAM_PACKAGE_NAME=""
export PARAM_DURATION=""
export PARAM_VERBOSE=false
export PARAM_RESULT_DIR=false
if [ $# -eq 0 ]; then
show_help_info
exit
else
PARAM=("$@")
I=0
while true; do
case ${PARAM[$I]} in
--pkg|-p)
I=`expr $I + 1`
PARAM_PACKAGE_NAME=${PARAM[$I]}
;;
--duration|-d)
I=`expr $I + 1`
PARAM_DURATION=${PARAM[$I]}
;;
--verbose)
PARAM_VERBOSE=true
;;
--result_dir)
I=`expr $I + 1`
PARAM_RESULT_DIR=${PARAM[$I]}
;;
*)
show_help_info
exit 1
;;
esac
I=`expr $I + 1`
if [ $I -eq $# ]; then
break;
fi
done
fi
#设置包名
if [ "$PARAM_PACKAGE_NAME" = "" ]; then
echo_red "Please specify the package name"
echo_red "ex: ./SamplingSysData-* com.xxx.xxx"
exit 1
fi
if [ "$PARAM_DURATION" = "" ]; then
PARAM_DURATION=5
echo_red "The default duration: ${PARAM_DURATION}"
fi
echo_v(){
if [ ${PARAM_VERBOSE} = true ]; then
echo_blue "$@"
fi
}
#设置U盘路径
export RESULT_PATH=""
if [ "${PARAM_RESULT_DIR}" = "" ]; then
RESULT_PATH="/data/SamplingSysDaya/$PARAM_PACKAGE_NAME";
else
RESULT_PATH="${PARAM_RESULT_DIR}/$PARAM_PACKAGE_NAME"
fi
res="result.$(date +%Y%m%d-%H%M%S).csv"
#设置 CPU 采样周期(s)
sampling_CPU_interval=5
a=0
#设置总次数
total=100000
if [ ! -d "$RESULT_PATH" ];
then
mkdir -p $RESULT_PATH
if [ $? -ne 0 ]; then
echo_red "You specifyc error path or you didn't have permission"
exit 1
fi
fi ;
# -----------------------------------------------------------------------------
#获取CPU个数
processor=$(cat /proc/cpuinfo| grep "processor"|wc -l)
# -----------------------------------------------------------------------------
# 获取 PID
export PROGRESS_PID=""
get_package_pid(){
PID=$(ps | grep "${1}" | sed 's/ [ ]*/ /g' - | cut -d' ' -f2 | xargs echo)
if [ "${PID}" = "" ]; then
PID=$(ps -A | grep "${1}" | sed 's/ [ ]*/ /g' - | cut -d' ' -f2 | xargs echo)
if [ "${PID}" = "" ]; then
exit 1
else
echo ${PID}
fi
else
echo ${PID}
fi
}
is_process_exist(){
safty_param="$@ end"
I=0
while true;
do
let "I += 1"
PID=$(echo ${safty_param}|cut -d' ' -f${I})
if [ ${PID} == end ]; then break; fi
if [ -f /proc/${PID}/stat ]; then
continue;
else
return 1
fi
done
return 0
}
get_pids_threadNumbers(){
safty_param="$@ end"
sum=0;
I=0
while true;
do
let "I += 1"
PID=$(echo ${safty_param}|cut -d' ' -f${I})
if [ ${PID} == end ]; then break; fi
nums=$(ls /proc/${PID}/task | wc -l)
let "sum+=${nums}"
done
echo ${sum}
}
PROGRESS_PID=$(get_package_pid ${PARAM_PACKAGE_NAME})
# -----------------------------------------------------------------------------
function get_disk_iow(){
export DISK_NAME;
if [ "$1" = "" ];then
DISK_NAME=mmcblk0
else
DISK_NAME=${1}
fi
export diskstate=$(cat /proc/diskstats | grep " ${DISK_NAME} " | sed 's/[ ][ ]*/ /g' -)
rt=$(echo ${diskstate}|cut -d' ' -f8)
wt=$(echo ${diskstate}|cut -d' ' -f12)
iot=$(echo ${diskstate}|cut -d' ' -f14)
let "sum=${rt}+${wt}+${iot}"
echo ${sum}
}
DISK_SUM_COST_TIME=$(get_disk_iow)
# -----------------------------------------------------------------------------
function get_pid_ticket(){
safty_param="$@ end"
sum=0;
I=0
while true;
do
let "I += 1"
PID=$(echo ${safty_param}|cut -d' ' -f${I})
if [ "$PID" == "end" ]; then
echo ${sum}
return
fi
stats=$(cat /proc/${PID}/stat)
utime=$(echo ${stats}|cut -d' ' -f14)
stime=$(echo ${stats}|cut -d' ' -f15)
let "sum+=${stime}+${utime}"
done
}
CPU_SUM_TIKI=$(get_pid_ticket ${PROGRESS_PID})
echo $CPU_SUM_TIKI
# -----------------------------------------------------------------------------
export t1=0
export t2=0
export t3=0
export t4=0
export t5=0
export DATE=0
export FLASH_USAGE=0
export MEM_USAGE=0
export CPU_USAGE=0
export IO_USAGE=0
# -----------------------------------------------------------------------------
rm -rf $RESULT_PATH/$res
echo "date,flash(KB),mem(KB),cpu(‰),iorw(ms),thread" >> $RESULT_PATH/$res
echo "date,flash(KB),mem(KB),cpu(‰),iorw(ms),thread"
#生成应用占用flash数据
while (($a < $total));do
if [ "${PROGRESS_PID}" = "" ]; then
is_process_exist ${PROGRESS_PID}
if [ $? -eq 1 ]; then
sleep 1
FLASH_USAGE=0
MEM_USAGE=0
CPU_USAGE=0
IO_USAGE=0
PROGRESS_PID=$(get_package_pid ${PARAM_PACKAGE_NAME})
continue;
fi
fi
# ------------------------------------------------------------
DATE=$(date "+%H:%M:%S")
# ------------------------------------------------------------
let "t4 += 1";
if [ $t4 -ge ${PARAM_DURATION} ]; then
t4=0;
# ------------------------------------------------------------
# Flash Usage
# du -sh /data/data/$PARAM_PACKAGE_NAME | sed 's/ [ ]*/ /g' - | cut -d" " -f1 >> $RESULT_PATH/flash.csv;
FLASH_USAGE=$(du -sh /data/data/${PARAM_PACKAGE_NAME} | sed 's/[ \t][ \t]*/ /g' - | cut -d" " -f1)
echo_v "FLASH_USAGE: ${FLASH_USAGE}"
# ------------------------------------------------------------
# mem usage
# 输出Meminfo大小 单位:M
# echo `dumpsys meminfo ${PARAM_PACKAGE_NAME} | grep "TOTAL SWAP" | sed 's/ [ ]*/ /g' - | cut -d' ' -f3` >>$RESULT_PATH/ddr.csv;
MEM_USAGE=$(dumpsys meminfo ${PARAM_PACKAGE_NAME} | grep "TOTAL SWAP" | sed 's/ [ ]*/ /g' - | cut -d' ' -f3)
echo_v "MEM_USAGE: ${MEM_USAGE}"
# ------------------------------------------------------------
# io usage
NOW_DISK_SUM=$(get_disk_iow)
let "diff=${NOW_DISK_SUM}-${DISK_SUM_COST_TIME}"
let "diff=${diff}/${PARAM_DURATION}"
IO_USAGE=${diff}
DISK_SUM_COST_TIME=${NOW_DISK_SUM}
echo_v "IO_USAGE: ${IO_USAGE}"
# ------------------------------------------------------------
# Thread numbs
# THREAD_NUM=`ls /proc/${PROGRESS_PID}/task | wc -l`
THREAD_NUM=$(get_pids_threadNumbers ${PROGRESS_PID})
echo_v "THREAD_NUM: ${THREAD_NUM}"
# echo "Thread Num: ${THREAD_NUM}"
fi
# ------------------------------------------------------------
let "t3 += 1";
if [ $t3 -ge ${sampling_CPU_interval} ]; then
t3=0;
tmpsum=$(get_pid_ticket ${PROGRESS_PID})
if [ $tmpsum -eq 0 ]; then
PROGRESS_PID=$(ps | grep "${PARAM_PACKAGE_NAME}" | sed 's/ [ ]*/ /g' - | cut -d' ' -f2 | xargs echo)
CPU_SUM_TIKI=$(get_pid_ticket ${PROGRESS_PID})
else
let "diff=${tmpsum}-${CPU_SUM_TIKI}"
let "diff=${diff}"
let "diff=${diff}/${processor}"
CPU_SUM_TIKI=${tmpsum}
CPU_USAGE=${diff}
echo_v "CPU_USAGE: ${CPU_USAGE}"
fi
fi
# ------------------------------------------------------------
let "t5 += 1";
if [ $t5 -ge ${PARAM_DURATION} ]; then
t5=0
echo "${DATE},${FLASH_USAGE},${MEM_USAGE},${CPU_USAGE},${IO_USAGE},${THREAD_NUM}"
# echo "DATE: ${DATE}"
# echo "FLASH_USAGE: ${FLASH_USAGE}"
# echo "MEM_USAGE: ${MEM_USAGE}"
# echo "CPU_USAGE: ${CPU_USAGE}"
# echo "IO_USAGE: ${IO_USAGE}"
# echo "THREAD_NUM: ${THREAD_NUM}"
echo "${DATE},${FLASH_USAGE},${MEM_USAGE},${CPU_USAGE},${IO_USAGE},${THREAD_NUM}" >> ${RESULT_PATH}/${res}
fi
sleep 1
done
![]() |
![]() |



浙公网安备 33010602011771号