前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战 | Android过度绘制自动化测试

实战 | Android过度绘制自动化测试

作者头像
岛哥的质量效能笔记
发布2021-08-18 15:09:08
4140
发布2021-08-18 15:09:08
举报
文章被收录于专栏:岛哥的质量效能笔记

阅读本文大约需要2.1分钟。

背景

应用可能会在单个帧内多次绘制同一个像素,这种情况称为“过度绘制”,过度绘制通常是不必要的,最好避免,它会浪费 GPU 时间来渲染与用户在屏幕上所见内容无关的像素,进而导致性能问题。

通过标准

背景颜色

表示的含义

无颜色

表示没有重绘,即一个像素点只被绘制了1次

蓝色

表示重绘了1次,即一个像素点被绘制了2次。屏幕上如果有大块的的蓝色区域是可以接受的,但如果整个屏幕都是蓝色的,那就需要优化了,可以去掉一层

绿色

表示重绘了2次,即一个像素点被绘制了3次。中等面积的绿色区域是可以接受的,不过最好引起警惕,去看一下能不能优化

淡红色

表示重绘了3次,即一个像素绘制了4次。很小的淡红色区域是可以接受的,其他情况就需要去优化

深红色

表示重绘了4次以上。这个不正确的,必须进行优化

手工测试方案

其实 Android 平台已经提供了工具来帮助我们确定过度绘制是否会影响应用的性能,如果是通过手工的方式,首先需要按照以下步骤打开显示过度绘制区域的选项:

代码语言:javascript
复制
设置 -> 开发者选项 -> 调试GPU过度绘制 -> 显示过度绘制区域

GPU 过度绘制调试工具使用颜色编码来显示应用在屏幕上绘制每个像素的次数,此计数越高,过度绘制影响应用性能的可能性越大。

开启调试开关后进入应用的所有页面进行检测是否有过度绘制的情况,现在的应用动辄都是上百个页面的,如果全手工来做,工作量和效率可想而知,所以接下来跟大家分享一下全自动化的方案。

自动化测试方案

Android 源码中有个叫 drawOverdrawCounter 的函数可以用来计算当前页面过度绘制的次数,所以我们可以通过Hook该函数来获得这个值,但是 drawOverdrawCounter 函数仅在Android 4.4.4源码中有实现,在Android 5.0之后就被去掉了,所以我们需要准备一台Android 4.4.4的模拟器或者真机,我用的是Genymotion的模拟器。

首先在模拟器中安装好Xposed框架,然后找到需要Hook的系统函数路径及参数,这里推荐大家一个可以快速检索Android各个版本系统源码的网站:

代码语言:javascript
复制
http://androidxref.com/

这样就找到了目标路径,点击进入查看详情:

会发现 drawOverdrawCounter 函数是在 android.view.HardwareRenderer 的内部类 GlRenderer 中,这样我们就可以通过Xposed来Hook获取过度绘制的值并将其实时写入到指定文件中。

下面是插件的具体实现方式:

代码语言:javascript
复制
package com.xposed.overdraw;

import android.annotation.SuppressLint;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;

public class CheckOverdraw implements IXposedHookLoadPackage {

    private float overDrawCounter;

    @Override
    public void handleLoadPackage(LoadPackageParam loadPackageParam) {

        try {
            Class<?> hookMessageListenerClass;
            hookMessageListenerClass = loadPackageParam.classLoader.loadClass("android.view.HardwareCanvas");
            findAndHookMethod("android.view.HardwareRenderer$GlRenderer", loadPackageParam.classLoader, "drawOverdrawCounter", hookMessageListenerClass, float.class, float.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) {
                    overDrawCounter = (float) param.args[1];
                    writeFileToSDCard(float2byte(overDrawCounter), null, "overDraw.txt", false, false);
                }
            });
        } catch (Throwable e) {
            Log.d("overdraw", e.toString());
        }
    }
}

将插件编译成APK安装到模拟器中,这时候打开先前安装的Xposed框架,进入Modules

会看到自己刚刚装的插件,点击开启重启模拟器即可生效

通过下面的命令切换show和count模式:

代码语言:javascript
复制
adb shell setprop debug.hwui.overdraw count //显示过度绘制的次数
adb shell setprop debug.hwui.overdraw show //显示过度绘制的色块详
adb shell cat /sdcard/overDraw.txt //查看过度绘制的次数

插件准备好之后,接下来就是实现我们的自动化测试脚本了,这里我是基于Airtest实现的,由于比较简单我就讲一下大致思路:

  • 首先准备好需要验证的页面schema地址,循环遍历
  • 每次跳转schema前通过命令行切换到count模式
  • 读取count的值,判断是否大于3,如果是切换到show模式,再次跳转同一个schema,截图保存

Xposed插件的完整实现参考下面的地址,阅读原文可查看:

代码语言:javascript
复制
https://github.com/logan62334/overdraw-xposedmodule,

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 岛哥的质量效能笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档