#$dirput: round app start_time(ms) start_type rss(MB) pss(MB) ratio pagefault itlbmiss dtlbmiss cpustalled cycle=3 while getopts ":s:c" opt do case $opt in s) export ANDROID_SERIAL=$OPTARG ;; c) cycle=$OPTARG ;; ?) echo "unrecognized parameters" $opt echo "usage: run.sh -s sid -c cycle" exit 1 ;; esac done # 检查多个设备 # 如果有多台设备需要先手动export ANDROID_SERIAL=xxx运作这个脚本 nr_dev=$(adb devices | grep -v "List of devices" | grep device -c) if [ $nr_dev -gt 1 ] && [ -z "$ANDROID_SERIAL" ] ; then echo "adb: more than one device/emulator" exit fi # 如果只有1台设备默认测试该设备 if [ -z "$ANDROID_SERIAL" ]; then sid=$(adb devices | grep -v "List of devices" | grep device | awk '{print $1}') export ANDROID_SERIAL=$sid fi # adb root并推送perfetto配置文件 adb root adb push perfconf.txt /data/misc/perfetto-configs dir=$ANDROID_SERIAL/$(/usr/bin/date +%Y-%m%d-%H%M) mkdir -p $dir mkdir $dir/system_mem mkdir $dir/battery mkdir $dir/traces mkdir $dir/meminfo mkdir $dir/simpleperf echo "round app start_type start_time inc_ratio inc_total rss pss pagefaults itlbmiss dtlbmiss cpustall" > $dir/result for round in $(seq 1 $cycle); do for app in `cat applist`; do sleep 3 # 抓内存相关信息 adb shell free -h > $dir/system_mem/before_free-$app-$round adb shell cat /proc/meminfo > $dir/system_mem/before_meminfo-$app-$round adb shell cat /proc/zoneinfo > $dir/system_mem/before_zoneinfo-$app-$round adb shell cat /proc/buddyinfo > $dir/system_mem/before_buddyinfo-$app-$round adb shell cat /proc/pagetypeinfo > $dir/system_mem/before_pagetypeinfo-$app-$round adb shell cat /proc/vmstat > $dir/system_mem/before_vmstat-$app-$round # 开始抓simpleperf和perfetto adb shell "simpleperf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,page-faults,raw-stall-backend-mem --app $app --duration 3 -o /data/local/tmp/simpleperf-"$app"-"$round".txt" & adb shell "perfetto -c /data/misc/perfetto-configs/perfconf.txt --txt -o /data/misc/perfetto-traces/trace-"$app"-"$round".ptrace" & perfetto_pid=$! # 获取应用activity if [ "$app" == "com.qiyi.video" ]; then activity="com.qiyi.video/com.qiyi.video.WelcomeActivity" elif [ "$app" == "com.netease.cloudmusic" ]; then activity="com.netease.cloudmusic/com.netease.cloudmusic.activity.IconChangeDefaultAlias" else activity=$(adb shell dumpsys package $app | grep -A 1 -w "android.intent.action.MAIN:" | head -n 2 | tail -n 1 | awk '{print $2}') fi if [ -z "$activity" ]; then continue fi # 睡眠1s并准备抓大页数据 sleep 1 echo "starting $activity" # 抓电池信息 adb shell "dumpsys battery" > $dir/battery/battery-$app-$round prev_alloc=$(adb shell cat /sys/kernel/mm/transparent_hugepage/hugepages-64kB/stats/anon_fault_alloc) prev_alloc_fallback=$(adb shell cat /sys/kernel/mm/transparent_hugepage/hugepages-64kB/stats/anon_fault_fallback) # 启动应用 adb shell am start -n $activity # 睡眠15s并等待perfetto退出 sleep 10 wait # 后面的dumpsys meminfo也会分配大页 # 所以先看分配大页数 alloc=$(adb shell cat /sys/kernel/mm/transparent_hugepage/hugepages-64kB/stats/anon_fault_alloc) alloc_fallback=$(adb shell cat /sys/kernel/mm/transparent_hugepage/hugepages-64kB/stats/anon_fault_fallback) # dump内存占用 adb shell "dumpsys meminfo --package $app" > $dir/meminfo/meminfo-"$app"-"$round".txt # 抓启动后的内存信息 adb shell free -h > $dir/system_mem/after_free-$app-$round adb shell cat /proc/meminfo > $dir/system_mem/after_meminfo-$app-$round adb shell cat /proc/zoneinfo > $dir/system_mem/after_zoneinfo-$app-$round adb shell cat /proc/buddyinfo > $dir/system_mem/after_buddyinfo-$app-$round adb shell cat /proc/pagetypeinfo > $dir/system_mem/after_pagetypeinfo-$app-$round adb shell cat /proc/vmstat > $dir/system_mem/after_vmstat-$app-$round # 睡眠3s后拉simpleperf和perfetto数据 sleep 10 adb pull /data/misc/perfetto-traces/trace-"$app"-"$round".ptrace $dir/traces adb pull /data/local/tmp/simpleperf-"$app"-"$round".txt $dir/simpleperf/ adb shell "rm /data/misc/perfetto-traces/trace-"$app"-"$round".ptrace" adb shell "rm /data/local/tmp/simpleperf-"$app"-"$round".txt" # 回到桌面,应用退后台 adb shell input keyevent 3 # 计算启动耗时 python3 handle_perfetto.py $dir/traces/trace-"$app"-"$round".ptrace mm > tmp.txt if [ $(cat tmp.txt | wc -l) -ne 1 ]; then start_time=0 start_type="NONE" else start_time=$(cat tmp.txt | awk '{print $1}') start_type=$(cat tmp.txt | awk '{print $2}') fi start_time=$((start_time/10000)) start_time=$(echo "scale=2; $start_time / 100" | bc) # 计算PSS RSS if [ $(cat $dir/meminfo/meminfo-"$app"-"$round".txt | grep "MEMINFO in pid" -c) -ne 1 ]; then cat $dir/meminfo/meminfo-"$app"-"$round".txt | grep "TOTAL PSS" | tail -n 1 > tmp.txt pss=$(cat tmp.txt | awk '{print $3}') rss=$(cat tmp.txt | awk '{print $6}') else cat $dir/meminfo/meminfo-"$app"-"$round".txt | grep "TOTAL PSS" > tmp.txt pss=$(cat tmp.txt | awk '{print $3}') rss=$(cat tmp.txt | awk '{print $6}') fi pss=$(echo "scale=2; $pss / 1024" | bc) rss=$(echo "scale=2; $rss / 1024" | bc) # 计算大页分配成功率 inc_alloc=$((alloc-prev_alloc)) inc_alloc_fallback=$((alloc_fallback-prev_alloc_fallback)) inc_total=$((inc_alloc+inc_alloc_fallback)) if [ $inc_total -ne 0 ]; then inc_ratio=$(echo "scale=4; $inc_alloc / $inc_total" | bc) else inc_ratio=1 fi pagefaults=$(cat $dir/simpleperf/simpleperf-"$app"-"$round".txt | grep 'page-faults' | awk '{print $4}') itlbmiss=$(cat $dir/simpleperf/simpleperf-"$app"-"$round".txt | grep 'iTLB-load-misses' | awk '{print $4}') dtlbmiss=$(cat $dir/simpleperf/simpleperf-"$app"-"$round".txt | grep 'dTLB-load-misses' | awk '{print $4}') cpustall=$(cat $dir/simpleperf/simpleperf-"$app"-"$round".txt | grep 'raw-stall-backend-mem' | awk '{print $4}') echo $round $app $start_type $start_time $inc_ratio $inc_total $rss $pss $pagefaults $itlbmiss $dtlbmiss $cpustall >> $dir/result rm tmp.txt done done