Android Graphics 显示系统 - Android Jank detection with FrameTimeline

“ 最近有公司同事在处理UI卡顿及FPS自动化监测的问题,我也顺便看了一点相关的内容,其中在Perfetto的官方说明文档中有一篇关于利用FrameTimeLine进行Jank监测的解读,个人觉得蛮有意思的,借助工具翻译该篇文章并加上本人拙劣的解读供大家把玩!

注意:Android 12(S)以及更高版本的安卓系统的SurfaceFlinger中才有实现FrameTimeLine的逻辑。

/frameworks/native/services/surfaceflinger/FrameTimeline/

英文好且对Graphics知识有一定了解的,无需阅读拙作,直接读英文原文即可,地址:

https://perfetto.dev/docs/data-sources/frametimeline


01 前言

Jank/Janky直译就是劣质的、不可靠的。如果一个Frame被认为出现了Jank,则说明该帧图像没有按照调度器给出的预计时间显示到屏幕上,通常就是显示晚了。

Jank会造成什么影响呢?

  • 不稳定的帧率 -- 比如正常是60fps,但因为Jank帧率可能只有50fps,导致画面不流畅;

  • 延迟增加 -- 在一些实时性要求高的场景,画面可能延时几个vsync显示,比如视频播放时AV不sync;

怎么监测Jank呢?

FrameTimeline是SurfaceFlinger中的一个模块,用于监测Jank并报告Jank的来源。

02 APP Timeline

对于至少有一帧画面显示到屏幕上的应用,在抓取的Perfetto信息中会看到两个Timeline轨迹:Expected Timeline 和 Actual Timeline

图片

Expected Timeline:预期时间线,每个切片表示应用程序渲染帧的时间。为了避免系统中出现janks,该应用程序预计将在此时间范围内完成。切片开始时间是Choreographer callback计划运行的时间。

Actual Timeline:这些切片表示应用程序完成帧的绘制(包括GPU工作)并将其发送给SurfaceFlinger进行合成所花费的实际时间。起始时间是Choreographer#doFrame或AChoreographer_vsyncCallback开始运行的时间。切片的结束时间表示 (gpu time, post time) 两者的最大值。post time是应用的帧发送到SurfaceFlinger的时间。

图片

看到这里大家会不会有什么疑问或发现?

对于Case 2,比较符合常规理解,CPU和GPU的工作都做完了,即APP的一帧图片绘制完成了,然后才送到SurfaceFlinger去显示;

对于Case 1,GPU的绘制还没完成就先送去SurfaceFlinger了,这不会有问题吧?当然不会,这就是acquire fence的意义了,不熟悉的可以参考前面文章

Android Graphics 显示系统 - GraphicBuffer同步机制-Fence(二十)

我们看Android 14代码中,主要是哪里在等待acquire fence:

CLIENT合成时,会调用到RenderEngine::drawLayers方法来呼叫GPU完成合成工作,要等到layer的buffer准备好后才能开始合成工作,此时就要等待acquire fence。

/frameworks/native/libs/renderengine/skia/SkiaRenderEngine.cpp
ftl::Future<FenceResult> RenderEngine::drawLayers(...) {
    ......
    drawLayersInternal(std::move(resultPromise), display, layers, buffer, useFramebufferCache,
                       std::move(bufferFence));
    return resultFuture;
}

/frameworks/native/libs/renderengine/skia/SkiaRenderEngine.cpp
void SkiaRenderEngine::drawLayersInternal(......) {
    ...
    if (layer.source.buffer.buffer) {
        ATRACE_NAME("DrawImage");

        // if the layer's buffer has a fence, then we must must respect the fence prior to using
        // the buffer.
        if (layer.source.buffer.fence != nullptr) {
            waitFence(grContext, layer.source.buffer.fence->get()); // 等待acquire fence
        }
    ...
}

DEVICE合成时,layer的buffer连同其acquire fence会送到HWC,HWC合成前会等待acquire fence。以/external/drm_hwcomposer为例来看:

点击阅读全文:

Android Jank detection with FrameTimeline

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值