Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[问答]如何获取android程序流畅度(SM: SMoothness) #236

Open
inexistence opened this issue Aug 26, 2015 · 8 comments
Open

[问答]如何获取android程序流畅度(SM: SMoothness) #236

inexistence opened this issue Aug 26, 2015 · 8 comments

Comments

@inexistence
Copy link

《如何量化Android应用的“卡”?—流畅度原理&定义篇》一文中,提到了

可以在Choreographer的回调FrameCallback中,按秒计数表示当前App的流畅程度,即流畅度SM(SMoothness)。

没大理解这里具体是怎么实现的,求教。

@harryhappy
Copy link

反编译他们看了一眼,监听系统log实现的。代码里有句log

do much thing in main thread 巴拉巴拉的
不太靠谱,尝试写了一下 似乎不太好用

@LLin233
Copy link

LLin233 commented Dec 16, 2015

每一帧渲染的时候log一次, 然后算下fps吧

Harry notifications@github.com于2015年12月15日周二 下午6:14写道:
反编译他们看了一眼,监听系统log实现的。代码里有句log

do much thing in main thread 巴拉巴拉的
不太靠谱,尝试写了一下 似乎不太好用


Reply to this email directly or view it on GitHub .

@harryhappy
Copy link

@LLin233 仔细看了一下,上面写的是文章里提到的另外一个概念“丢帧”数。
监听 Choreographer 中 doFrame()中的一句log
Log.i(TAG, "Skipped " + skippedFrames + " frames! " + "The application may be doing too much work on its main thread.");
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.2_r1/android/view/Choreographer.java?av=f
还是不知道SM: SMoothness这个值是怎么实现的

@harryhappy
Copy link

反编译了,代码里主要有两个service:
SMLogService SMDataService

SMLogService 比较清晰就是在监听log, SMDataService 看不懂在搞什么啊
大家一起看看
通过监听log获取丢帧数的那个地方比较清晰,SM获取还是不清晰
dex2jar 反编译的好像有丢失信息,大家一起看看smali

@yoomaz
Copy link

yoomaz commented Dec 17, 2015

Choreographer 的api里这样描述这个类的 :Each Looper thread has its own choreographer ,但是我只能打出一个log的数值,难道是因为16ms一此,太快了log打印不出来》

@xiaosongluo
Copy link

SM(Smooth,流畅度)、SF(SkippedFrame,跳帧)

基础数据来源背景:
从Android 4.1(版本代号为Jelly Bean)开始,Android OS开发团队便引入了三个核心元素,即VSYNC、Triple Buffer和Choreographer力图解决严重影响Android口碑问题之一的UI流畅性差的问题。
而其中,Choreographer的主要功能是,当收到VSYNC信号时,在doFrame()里去调用使用者通过postCallback设置的回调函数。目前一共定义了三种类型的回调,它们分别是:
CALLBACK_INPUT:优先级最高,和输入事件处理有关。
CALLBACK_ANIMATION:优先级其次,和Animation的处理有关。
CALLBACK_TRAVERSAL:优先级最低,和UI等控件绘制有关。这个函数里面主要是检查当前窗口当前状态,比如说是否依然可见,尺寸,方向,布局是否发生改变(可能是由前面的用户输入触发的),分别调用performMeasure(), performLayout(), performDraw()来完成测量,布局和绘制工作。
由于VSYNC信号每16.6ms产生一次(具体时间依据系统实现),因此理想情况下每秒可执行绘制相关操作60次。但实际情况是,CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL中任意一个节点都有可能因为存在耗时操作而导致doFrame()无法在16.6ms内完成,从而无法在接下来的VSYNC信号到达时进行处理。
因此,SM(Smooth,流畅度)、SF(SkippedFrame,跳帧均选用Choreographer中doFrame()实际执行的次数作为基础数据。

指标计算方法:
SF(SkippedFrame,跳帧),即为某个应用程序在单位时间1秒内,跳过执行Choreographer中doFrame()的次数。
SM(Smooth,流畅度),即为某个应用程序在单位时间1秒内,实际执行Choreographer中doFrame()的次数。在获取SF数值的基础上,SM=60-SF。
连续跳帧,与SF的不同在于,它将跳帧按其连续跳帧数进行统计,用以衡量单位时间内的卡顿程度。

指标获取方式:
相关源码:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/Choreographer.java#Choreographer.doFrame%28long%2Cint%29

void More ...doFrame(long frameTimeNanos, int frame) {
510 final long startNanos;
511 synchronized (mLock) {
512 if (!mFrameScheduled) {
513 return; // no work to do
514 }
515
516 startNanos = System.nanoTime();
517 final long jitterNanos = startNanos - frameTimeNanos;
518 if (jitterNanos >= mFrameIntervalNanos) {
519 final long skippedFrames = jitterNanos / mFrameIntervalNanos;
520 if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
521 Log.i(TAG, "Skipped " + skippedFrames + " frames! "
522 + "The application may be doing too much work on its main thread.");
523 }
524 final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
525 if (DEBUG) {
526 Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
527 + "which is more than the frame interval of "
528 + (mFrameIntervalNanos * 0.000001f) + " ms! "
529 + "Skipping " + skippedFrames + " frames and setting frame "
530 + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
531 }
532 frameTimeNanos = startNanos - lastFrameOffset;
533 }
534
535 if (frameTimeNanos < mLastFrameTimeNanos) {
536 if (DEBUG) {
537 Log.d(TAG, "Frame time appears to be going backwards. May be due to a "
538 + "previously skipped frame. Waiting for next vsync.");
539 }
540 scheduleVsyncLocked();
541 return;
542 }
543
544 mFrameScheduled = false;
545 mLastFrameTimeNanos = frameTimeNanos;
546 }

SF(SkippedFrame,跳帧),注:SM(Smooth,流畅度)的获取方式基于SF(SkippedFrame,跳帧)的获取,SM=60-SF
通过注入的方式,获取skippedFrames的数值,并进行处理,通过GT测试工具实现。

@xiaosongluo
Copy link

GT工具的开源的地址:https://github.com/TencentOpen/GT

@harryhappy
Copy link

https://github.com/TencentOpen/GT
哦哦哦 开源了啊 研究下源码吧。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants