当前位置:网站首页>6章 性能平台GodEye源码分析-自定义拓展模块
6章 性能平台GodEye源码分析-自定义拓展模块
2022-07-17 00:09:00 【许英俊】
6. 自定义拓展模块
6.1 FrameLoss

FrameLoss指的是设置的丢帧率,在GodEye并没有当前的指标,此指标是根据当前项目需要自定义的拓展项目,如果连接USB线,可以通过以下命令看到当前的丢帧率Janky frames: 32 (6.61%),但由于系统无法通过执行命令的方式去获取,只能通过反射的方法去获取,目前只适配于低版本的获取方式
adb shell dumpsys gfxinfo com.example.mobile
源码分析
1、启动FrameLoss的监控
模仿GodEye的代码,FrameLoss的监控通过启动定时器,按xml配置的时间进行采集,通过frameLossUsage.getFrameLossInfo()获取FrameLoss信息
public class FrameLossEngine implements Engine {
private Producer<FrameLossInfo> mProducer;
private long mIntervalMillis;
private CompositeDisposable mCompositeDisposable;
private FrameLossUsage frameLossUsage;
public FrameLossEngine(Producer<FrameLossInfo> producer, long intervalMillis) {
mProducer = producer;
mIntervalMillis = intervalMillis;
mCompositeDisposable = new CompositeDisposable();
frameLossUsage = new FrameLossUsage();
}
@Override
public void work() {
mCompositeDisposable.add(Observable.interval(mIntervalMillis, TimeUnit.MILLISECONDS)
.subscribeOn(ThreadUtil.computationScheduler())
.observeOn(ThreadUtil.computationScheduler())
.map(new Function<Long, FrameLossInfo>() {
@Override
public FrameLossInfo apply(Long aLong) throws Exception {
return frameLossUsage.getFrameLossInfo();
}
})
.filter(new Predicate<FrameLossInfo>() {
@Override
public boolean test(FrameLossInfo frameLossInfo) throws Exception {
if (!frameLossInfo.isSupportFrameLoss) {
Log.d(L.DEFAULT_TAG, "当前不支持帧率测试");
shutdown();
}
return FrameLossInfo.INVALID != frameLossInfo;
}
}
)
.subscribe(new Consumer<FrameLossInfo>() {
@Override
public void accept(FrameLossInfo food) throws Exception {
mProducer.produce(food);
}
}));
}
@Override
public void shutdown() {
mCompositeDisposable.dispose();
}
}
2、采集FrameLoss信息
通过反射和匹配对应的字段去获取我们想要的Janky frames: 32 (6.61%)作为丢帧率的数据
- 反射
ActivityThread$ApplicationThread的dumpGfxInfo方法 - 通过流的方式拿到数据后,再去匹配对应的Janky帧数和Janky帧率
public class FrameLossUsage {
Pattern totalFramesRenderPattern = Pattern.compile("([0-9]+)");
Pattern JankyFramesPattern = Pattern.compile("([0-9]+)");
Pattern JankyFramesRatioPattern = Pattern.compile("(\\(.*\\))");
public FrameLossInfo getFrameLossInfo() {
return getFrameLossFromAT();
}
/** * Stats since: 14227634998581ns * Total frames rendered: 484 * Janky frames: 32 (6.61%) * 50th percentile: 6ms * 90th percentile: 10ms * 95th percentile: 18ms * 99th percentile: 150ms * Number Missed Vsync: 21 * Number High input latency: 0 * Number Slow UI thread: 19 * Number Slow bitmap uploads: 0 * Number Slow issue draw commands: 19 * HISTOGRAM: 5ms=166 6ms=105 7ms=95 8ms=53 9ms=15 10ms=9 11ms=2 12ms=1 13ms=1 14ms=3 15ms=1 16ms=3 17ms=4 18ms=4 19ms=1 20ms=0 21ms=0 22ms=0 23ms=0 24ms=0 25ms=0 26ms=0 27ms=0 28ms=0 29ms=0 30ms=0 31ms=0 32ms=0 34ms=1 36ms=0 38ms=0 40ms=0 42ms=1 44ms=0 46ms=0 48ms=0 53ms=0 57ms=0 61ms=0 65ms=0 69ms=1 73ms=0 77ms=0 81ms=0 85ms=0 89ms=2 93ms=1 97ms=1 101ms=2 105ms=0 109ms=0 113ms=1 117ms=1 121ms=1 125ms=0 129ms=1 133ms=1 150ms=7 200ms=0 250ms=0 300ms=0 350ms=0 400ms=0 450ms=0 500ms=0 550ms=0 600ms=0 650ms=0 700ms=0 750ms=0 800ms=0 850ms=0 900ms=0 950ms=0 1000ms=0 1050ms=0 1100ms=0 1150ms=0 1200ms=0 1250ms=0 1300ms=0 1350ms=0 1400ms=0 1450ms=0 1500ms=0 1550ms=0 1600ms=0 1650ms=0 1700ms=0 1750ms=0 1800ms=0 1850ms=0 1900ms=0 1950ms=0 2000ms=0 2050ms=0 2100ms=0 2150ms=0 2200ms=0 2250ms=0 2300ms=0 2350ms=0 2400ms=0 2450ms=0 2500ms=0 2550ms=0 2600ms=0 2650ms=0 2700ms=0 2750ms=0 2800ms=0 2850ms=0 2900ms=0 2950ms=0 3000ms=0 3050ms=0 3100ms=0 3150ms=0 3200ms=0 3250ms=0 3300ms=0 3350ms=0 3400ms=0 3450ms=0 3500ms=0 3550ms=0 3600ms=0 3650ms=0 3700ms=0 3750ms=0 3800ms=0 3850ms=0 3900ms=0 3950ms=0 4000ms=0 4050ms=0 4100ms=0 4150ms=0 4200ms=0 4250ms=0 4300ms=0 4350ms=0 4400ms=0 4450ms=0 4500ms=0 4550ms=0 4600ms=0 4650ms=0 4700ms=0 4750ms=0 4800ms=0 4850ms=0 4900ms=0 4950ms=0 * <p> * Caches: * Current memory usage / total memory usage (bytes): * TextureCache 0 / 75497472 * LayerCache 0 / 50331648 (numLayers = 0) * Layers total 0 (numLayers = 0) * RenderBufferCache 0 / 8388608 * GradientCache 0 / 1048576 * PathCache 0 / 33554432 * TessellationCache 0 / 1048576 * TextDropShadowCache 0 / 6291456 * PatchCache 0 / 131072 * FontRenderer A8 14215 / 1048576 * A8 texture 0 14215 / 1048576 * FontRenderer RGBA 0 / 0 * FontRenderer total 14215 / 1048576 * Other: * FboCache 0 / 0 * Total memory usage: * 1048576 bytes, 1.00 MB * <p> * <p> * Pipeline=FrameBuilder * Profile data in ms: * <p> * com.mobile.duowan.yygodeyes/com.mobile.duowan.yygodeyes.MainActivity/[email protected] (visibility=0) * View hierarchy: * <p> * com.mobile.duowan.yygodeyes/com.mobile.duowan.yygodeyes.MainActivity/[email protected] * 14 views, 17.12 kB of display lists * <p> * <p> * Total ViewRootImpl: 1 * Total Views: 14 * Total DisplayList: 17.12 kB */
private FrameLossInfo getFrameLossFromAT() {
FrameLossInfo frameLossInfo = new FrameLossInfo();
String path = GodEye.instance().getApplication().getCacheDir().getAbsolutePath();
//拿数据
FileDescriptor fd = null;
FileOutputStream fos = null;
File gfxFile = new File(path + File.separator + "gfx.txt");
try {
if (!gfxFile.exists()) {
gfxFile.createNewFile();
}
fos = new FileOutputStream(gfxFile);
fos.write(("").getBytes());
fos.flush();
fd = fos.getFD();
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
Field mAppThread = currentActivityThread.getClass().getDeclaredField("mAppThread");
mAppThread.setAccessible(true);
Object applicationThread = mAppThread.get(currentActivityThread);
Class<?> application = Class.forName("android.app.ActivityThread$ApplicationThread");
Method method = application.getDeclaredMethod("dumpGfxInfo", new Class[]{
FileDescriptor.class, String[].class});
method.setAccessible(true);
method.invoke(applicationThread, fd, new String[]{
GodEye.instance().getApplication().getPackageName()});
} catch (Exception e) {
frameLossInfo.isSupportFrameLoss = false;
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//读数据
BufferedReader bfr = null;
try {
bfr = new BufferedReader(new FileReader(gfxFile));
String line = bfr.readLine();
while (line != null) {
if (line.contains("Total frames rendered")) {
frameLossInfo.allFrameNumber = getPatternDoubleValue(totalFramesRenderPattern, line);
} else if (line.contains("Janky frames")) {
frameLossInfo.frameLoseNumber = getPatternDoubleValue(JankyFramesPattern, line);
frameLossInfo.frameLoseRatio = getPatternDoubleValueWithoutBracket(JankyFramesRatioPattern, line);
break;
}
line = bfr.readLine();
}
} catch (Exception e) {
frameLossInfo.isSupportFrameLoss = false;
e.printStackTrace();
} finally {
if (bfr != null) {
try {
bfr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
L.d(frameLossInfo.toString());
return frameLossInfo;
}
/** * 获取对应的正则表达式 * * @param pattern * @param cost * @return */
public Double getPatternDoubleValue(Pattern pattern, String cost) {
Matcher matcher = pattern.matcher(cost);
if (matcher.find()) {
return Double.valueOf(matcher.group().trim());
}
return (double) 0;
}
/** * 获取对应的正则表达式,并去掉括号和百分号 (6.63%) * * @param pattern * @param cost * @return */
public Double getPatternDoubleValueWithoutBracket(Pattern pattern, String cost) {
Matcher matcher = pattern.matcher(cost);
if (matcher.find()) {
return Double.valueOf(matcher.group().substring(1, matcher.group().length() - 2).trim());
}
return (double) 0;
}
}
3、总结
丢帧率的获取通过当前方式去获取,但需要适配高版本的获取,它可以应用在一些流畅度的指标上,让应用更加流畅
边栏推荐
- nft发行价格是多少(解读NFT建立起NFT世界观)
- The interviewer asked: how to check if redis suddenly slows down?
- The use of libtomcrypt password Library
- 深度伪造对国家安全的挑战及应对
- 通信感知一体化应用场景、关键技术和网络架构
- 我已经妥协了 大家既然都要叫我yelin 那我也没办法了
- phthon3 安装 MySQLdb 报错问题解决 Reason: image not found
- 元宇宙会给万亿市场的音乐产业带来哪些变化?
- WKWebView 设置自定义UserAgent正确姿势
- Today's code farmer girl learned about nodejs and repl interactive interpreter
猜你喜欢

蛟分承影,雁落忘归——袋鼠云一站式全自动化运维管家ChengYing(承影)正式开源

Redis suddenly slowed down?

Database connection pool and serialize to realize operations such as adding, deleting, changing and querying
![[AHU2021校内赛] ez-injection](/img/44/644c27f86cbbc9c6630249d2111066.png)
[AHU2021校内赛] ez-injection

MapReduce environment preparation

06 BTC mining difficulty

一文盘点估值超过1亿美元的NFT项目

解决scala无法对Native进行类的初始化

MapReduce

ethereum rpc
随机推荐
大数据开源项目,一站式全自动化全生命周期运维管家ChengYing(承影)走向何方?
一种5G空口单向时延及其可靠性的测量方法
走好数据中台最后一公里,为什么说数据服务API是数据中台的标配?
温州大学X袋鼠云:高等人才教育建设,如何做到“心中有数”
基于开源流批一体数据同步引擎ChunJun数据还原—DDL解析模块的实战分享
普通异步发送代码编写
Introduction to software vulnerability analysis (III)
mysql innodb 事务相关记录
JVM 判断对象已死,实践验证GC回收
手把手带你从零开始完整开发经典游戏【俄罗斯方块】,全部逻辑只用不到200行代码。
基于机器学习技术的无线小区负载均衡自优化
Nmap and Nikto scanning
How to use express and how to match and use routes
毒瘤 DDD
DHFS读写流程
TCP and UDP, TCP server and client, UDP server and client
基于移动互联网应用的儿童网络保护产业实践与完善
Xcode11新建项目后的一些问题
Basic use of promise
NFT-数字藏品之库里为何花116万买一个NFT头像?回顾NFT头像的“发迹史”或许能找到答案