shell 脚本通过 dumpsys SurfaceFlinger

您所在的位置:网站首页 csv文件读出来会有双引号吗 shell 脚本通过 dumpsys SurfaceFlinger

shell 脚本通过 dumpsys SurfaceFlinger

#shell 脚本通过 dumpsys SurfaceFlinger | 来源: 网络整理| 查看: 265

开篇前述:

由于采购机械臂测试性能用例和屏幕实际帧率变化,最终工具方案实现后搁置,拿出来” 晒晒 “。

一、设计初衷

1、面临用户和公司内领导试用中反馈的卡顿问题,思考如何能有效量化评估? 2、如何在尝试复现卡顿的过程中持续监控 FPS 和丢帧情况?

二、设定预期倒推查找解决方案

1、无 root 权限限制,可直接采集数据计算 FPS、丢帧率、最大单帧间隔。 2、控制脚本影响,不要使监控脚本成为 “负担”。 3、数据获取灵活,即可控制台实时输出数据,也可以后台长时间监控。 4、设计评价得分标准,可按:百分比 * 用例单项评分量化每条用例,从而计算总分使用。

设计实现部分

参考了网上现有的 FPS 计算方式原理,绕来绕去也没有满足自己的预期需求,索性自己从数据源出发自己设计脚本计算逻辑处理。参考如下 用第三方库 (surface_stats_collector.py) 获取 AndroidFPS 过程分析 (https://testerhome.com/topics/2232) 如何准确评测 Android 应用的流畅度? (http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=75&extra=page%3D1)

一、确定数据来源原因(dumpsys SurfaceFlinger --latency)

1、可以清零重新记录,避免如何分清哪些数据是上次的。(dumpsys SurfaceFlinger --latency-clear) 2、按 window 获取数据,可以配合手工操作逐一获取每个 case 的流畅度。 3、历史记录 127 行数据,按 60 帧算可记录 2.12S 数据,从而不用频繁获取。(最终考虑设定 1.6S 间隔刷新数据。)

二、根据需求确定计算规则

1、有刷新则计算帧率,无刷新则不输出数据。 原因: (1)要做成监控指定窗口流畅度的功能,所以要控制无意义数据。 (2)配合手工操作,静置状态不输出,操作停止后直接刷新数据,从而使数据和操作对应。 2、间隔 500ms 以上则判定为操作延迟,每到间隔 500ms 情况发生重新计算帧率。 原因: (1)一般做 monkey 压力测试设置的是 500ms 间隔 (2)一般用户操作频率间隔是大于 500ms 情况 3、每次采样数据大于等于 1 帧则计算 FPS,丢帧率,最大帧间隔。 原因:帧数/总耗时=帧率,所以无论有多少帧都可以直接计算 4、设定流畅度评价规则: (1)满足 KPI 帧率则达成一半需求,占比 50% (2)小于 KPI 单帧耗时比例评价画面变化是否稳定,占比 40% (3)单帧渲染峰值代表瞬时卡顿最大影响,占比 10% 5、代码实现过程中遇到一坑:SurfaceFlinger 中同一帧存在间隔复用情况,即相同一行数据间隔几帧出现两次。(通过监控微信红包点击后的弹出框的帧率发现的。) 补充规则:发生两帧同步时间做差小于第一行帧刷新周期,则总时间 + 帧刷新周期,上一帧数据=前一帧同步时间 + 帧刷新周期,总帧数 +1

三、代码实现 #!/system/bin/sh show_help() { echo " Usage: sh fps.sh [ -t target_FPS ] [ -w monitor_window ] [ -k KPI ] [ -f csv_path ] [ -h ] Show: FU(s) LU(s) Date FPS Frames jank MFS(ms) OKT SS(%) FU(s): Uptime of the first frame. LU(s): Uptime of the last frame. Date: The date and time of LU. FPS: Frames Per Second. Frames: All frames of a loop. jank: When the frame latency crosses a refresh period, jank is added one. MFS(ms): Max Frame Spacing. OKT: Over KPI Times. The KPI is the used time of one frame. SS(%): Smoothness Score. SS=(FPS/target FPS)*60+(KPI/MFS)*20+(1-OKPIT/Frames)*20 IF FPS > target FPS: FPS/The target FPS=1 IF KPI > MFS: KPI/MFS=1 WN: the window number of same name's window. Eg. SurfaceView POSIX options | GNU long options -t | --target The target FPS of the choosed window. Default: 60 -w | --window The choosed window. Default: no window. -k | --KPI The used time of a frame. Default: KPI=1000/The target FPS. -f | --file The path of the csv file. Default: output result to console. -h | --help Display this help and exit " } file="" window="" target=60 KPI=16 while : do case $1 in -h | --help) show_help exit 0 ;; -t | --target) shift target=$1 KPI=$((1000/$1)) shift ;; -w | --window) shift window="$1" shift ;; -k | --KPI) shift KPI=$1 shift ;; -f | --file) shift file="$1" shift ;; --) # End of all options shift break ;; *) # no more options. Stop while loop break ;; esac done if [ -f /data/local/tmp/busybox ];then export bb="/data/local/tmp/busybox" else echo "No /data/local/tmp/busybox" exit fi if [ -f /data/local/tmp/stop ];then $bb rm /data/local/tmp/stop fi if [ -f /data/local/tmp/FPS.pid ];then pid=`cat /data/local/tmp/FPS.pid` if [ -f /proc/$pid/cmdline ];then if [ `$bb awk 'NR==1{print $1}' /proc/$pid/cmdline`"a" == "sha" ];then echo "The $pid is sh command." exit fi fi fi echo $$ >/data/local/tmp/FPS.pid if [ $target -le 60 -a $target -gt 0 ];then sleep_t=1600000 else echo "$target is out of (0-60]" exit fi mac=`cat /sys/class/net/*/address|$bb sed -n '1p'|$bb tr -d ':'` model=`getprop ro.product.model|$bb sed 's/ /_/g'` build=`getprop ro.build.fingerprint` if [ -z $build ];then build=`getprop ro.build.description` fi uptime=`$bb awk -v T="$EPOCHREALTIME" 'NR==3{printf("%.6f",T-$3/1000000000+8*3600)}' /proc/timer_list` if [ -z "$file" ];then echo "" echo `date +%Y/%m/%d" "%H:%M:%S`": $window" if [ `$bb awk -F. '{print $1}' /proc/uptime` -lt 1000 ];then echo -e "FU(s) \tLU(s) \tDate \t\t\tFPS:$target\tFrames\tjank\tjank2\tMFS(ms)\tOKT:$KPI\tSS(%)\tWN" else echo -e "FU(s) \t\tLU(s) \t\tDate \t\t\tFPS:$target\tFrames\tjank\tjank2\tMFS(ms)\tOKT:$KPI\tSS(%)\tWN" fi while true;do dumpsys SurfaceFlinger --latency-clear $bb usleep $sleep_t dumpsys SurfaceFlinger --latency "$window"|$bb awk -v time=$uptime -v target=$target -v kpi=$KPI '{if(NR==1){r=$1/1000000;if(r0&&$0=="")O=1;if(NF==3&&$2!=0&&$2!=9223372036854775807){x=($3-$1)/1000000/r;if(b==0){b=$2;n=1;d=0;D=0;if(x1){d+=1;C=int(x)*r;if(x%1>0)C+=r};if(x>2)D+=1;m=r;o=0}else{c=($2-b)/1000000;if(c>500){O=1}else{n+=1;if(c>=r){C+=c;if(c>kpi)o+=1;if(c>=m)m=c;if(x>1)d+=1;if(x>2)D+=1;b=$2}else{C+=r;b=sprintf("%.0f",b+r*1000000)}}};if(n==1)s=sprintf("%.3f",$2/1000000000)};if(n>0&&O==1){O=0;if(n==1)t=sprintf("%.3f",s+C/1000);else t=sprintf("%.3f",b/1000000000);T=strftime("%F %T",time+t)"."sprintf("%.0f",(time+t)%1*1000);f=sprintf("%.2f",n*1000/C);m=sprintf("%.0f",m);g=f/target;if(g>1)g=1;h=kpi/m;if(h>1)h=1;e=sprintf("%.2f",g*60+h*20+(1-o/n)*20);print s"\t"t"\t"T"\t"f+0"\t"n"\t"d"\t"D"\t"m"\t"o"\t"e"\t"w;n=0;if($0==""){b=0;w+=1}else{b=$2;n=1;d=0;D=0;if(x1){d+=1;C=int(x)*r;if(x%1>0)C+=r};if(x>2)D+=1;m=r;o=0}}}}' if [ -f /data/local/tmp/stop ];then break fi done else start_time="`date +%Y/%m/%d" "%H:%M:%S`" echo "PID:$$\nWindow:$window\nT-FPS:$target\nKPI:$KPI\nStart time:$start_time\nmodel:$model\nmac:$mac\nbuild:$build" echo "FU(s),LU(s),Date:$window,FPS:$target,Frames,jank,jank2,MFS(ms),OKT:$KPI,SS(%),WN" >$file while true;do dumpsys SurfaceFlinger --latency-clear if [ -f /data/local/tmp/stop ];then echo "Stop Time:`date +%Y/%m/%d" "%H:%M:%S`" break fi $bb usleep $sleep_t dumpsys SurfaceFlinger --latency "$window"|$bb awk -v time=$uptime -v target=$target -v kpi=$KPI '{if(NR==1){r=$1/1000000;if(r0&&$0=="")O=1;if(NF==3&&$2!=0&&$2!=9223372036854775807){x=($3-$1)/1000000/r;if(b==0){b=$2;n=1;d=0;D=0;if(x1){d+=1;C=int(x)*r;if(x%1>0)C+=r};if(x>2)D+=1;m=r;o=0}else{c=($2-b)/1000000;if(c>500){O=1}else{n+=1;if(c>=r){C+=c;if(c>kpi)o+=1;if(c>=m)m=c;if(x>1)d+=1;if(x>2)D+=1;b=$2}else{C+=r;b=sprintf("%.0f",b+r*1000000)}}};if(n==1)s=sprintf("%.3f",$2/1000000000)};if(n>0&&O==1){O=0;if(n==1)t=sprintf("%.3f",s+C/1000);else t=sprintf("%.3f",b/1000000000);T=strftime("%F %T",time+t)"."sprintf("%.0f",(time+t)%1*1000);f=sprintf("%.2f",n*1000/C);m=sprintf("%.0f",m);g=f/target;if(g>1)g=1;h=kpi/m;if(h>1)h=1;e=sprintf("%.2f",g*60+h*20+(1-o/n)*20);print s","t","T","f+0","n","d","D","m","o","e","w;n=0;if($0==""){b=0;w+=1}else{b=$2;n=1;d=0;D=0;if(x1){d+=1;C=int(x)*r;if(x%1>0)C+=r};if(x>2)D+=1;m=r;o=0}}}}' >>$file done fi 四、监控数据可视化交互结果设计

既然设计了数据监控的形式,自然要设计配套的数据可视化呈现方式 1、呈现数据 (1)x 轴为同步时间点,每次采样数据为起始时间点到采样结束时间的一条横线。 (2)y 轴数据为平均 FPS、超 KPI 帧数比例、和流畅度得分。左右双 y 轴设计,左侧为帧率,右侧为百分比。 (3)两次数据起始时间间隔超 500ms 则断开 (4)每点交互数据显示此次原始数据记录 (5)按每次间隔时间超过 500ms 为准计算每次操作对应的响应时长,作图呈现。持续监控情况则每超 10 秒计算一次。 2、一次监视频控播放窗口结果图实例: 下方总趋势图是可选的,鼠标按住左键拖动选取查看范围。

五、脚本源码

(https://pan.baidu.com/s/1qYjzIZ6)

原理介绍引用

下面文章介绍的挺清晰的,虽然实现方案不一样,但原理出发点一样,可以作为参考文章。 (http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=936&extra=page%3D1)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3