Systrace 中的这些 tag 究竟是什么意思(一)| 掘金技术征文-双节特别篇

4,122 阅读8分钟

前言

本文是新栏目—— “simowce 黑板报” 的第 1 篇(构造函数的妙用 应该算第 0 篇 :-> 程序员的冷笑话)。在这个系列中,我会跟大家分享一些有趣,有用的知识点,篇幅不会很长,但是保证满满都是干货。因此如果大家觉得内容有用,希望大家可以将这个公众号**“设为星标”**,这样只要这个公众号一更新你就可以第一时间收到通知了。

今天分享的是 Systrace 中的 tag 的详细解释,一个 Systrace 里面内容繁多,它都有展示了哪些内容?这些内容具体都是什么意思?又有什么作用?别急,听我慢慢道来。

HW_VSYNC_ON_XXX

HW_VSYNC_ON
HW_VSYNC_ON

值类型

布尔值,1 表示 HW VSYNC 信号开关被打开,0 表示开关被关闭。

出现时机

HW VYSNC 硬件信号被打开和关闭的时候。

解释

首先,HW_VSYNC_ON_XXX 后面的 XXX 一般是一串数字,代表的是 displayid,如果你的机器有外接了显示器,那么可以通过 displayid 来区分不同的屏幕的 HW VSYNC 硬件信号。下面的 HW_VSYNC_XXX 中的 XXX 意义也是一样的。

HW VSYNC 硬件信号之所以会被一直打开关闭,主要原因是目前 Android Display/Graphic framework 依赖的信号不是硬件信号,而是软件信号——DispSync。HW VSYNC 只是用来做校准,打开的时机是当软件 VSYNC 的误差超过一定阈值以后,DispSync 就会主动打开 HW VSYNC 信号来做校准,(目前是)接收 6 个硬件信号以后就会关闭。这里就不过多展开描述,详细的说明感兴趣地可以看看这篇我之前写的 这篇文章,详细地描述了 DispSync 的各种细节。

作用

对于大部分的上层开发者来说其实是不需要关心这个 tag 的,因为大家都是在硬件没有 bug 的前提下进行工作的。但是这个前提对于手机厂商的研发人员是不成立的,因此这个 tag 就非常有用,可以用来作为分析项目前期硬件侧导致的各种 bug 的时间锚点。

HW_VSYNC_XXX

HW_VSYNC in Systrace
HW_VSYNC in Systrace

值类型

瞬时布尔值,从 1 变成 0 或者 0 变成 1 都表示当前时刻发出了 HW_VSYNC。

出现时机

HW VSYNC 硬件信号发出的时候。

解释

需要说明很重要的一点,从 Systrace 看,HW_VSYNC_XXX 似乎是一个区间,如上图所示。

但是实际上,Systrace 中的 HW_VSYNC_XXX 应该这么解读:

HW_VSYNC_XXX 的值是一个瞬时值,记录的是在当前时刻收到了 HW VSYNC 硬件信号,因此在 Systrace 中,当 HW_VSYNC_XXX 的值从 1 变成 0 或者从 0 变成 1,都代表着收到了 HW VSYNC 信号,类似于示波器中的脉冲信号一样。看一下在代码中是如何表示这个你就明白了:

bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
    ......
    const auto tag = "HW_VSYNC_" + to_string(*displayId);
    ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
    displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;

    return true;
}

当收到硬件的 HW VSYNC 信号之后,HWComposer::onVsync() 这个函数就会被回调,接着这个 displayData.vsyncTraceToggle 的值就会被一直取反,模拟出一个脉冲信号的样子并赋给 HW_VSYNC_XXX

而前面我们在 HW_VSYNC_ON_XXX 提到的,DispSync 在收到 6 个 HW VSYNC 硬件信号之后就会把 HW VSYNC 关闭,这个行为在 Systrace 中是怎么体现的呢?还是上面那张图,但是我们加了一些标记:

HW_VSYNC_ON.png-62.4kB
HW_VSYNC_ON.png-62.4kB

这样是不是就很清晰直观了?

因此这种类型我们取名为瞬时布尔值,表示只有在数值发生变化的时刻才有意义。

作用

跟 HW_VSYNC_XXX 一样,大部分人是用不到的。你应该无法想象 HW VSYNC 硬件信号会有不发或者乱发的问题哈哈。

hasClientComposition

hasClientComposition
hasClientComposition

值类型

布尔值,1 表示本次合成有 GPU 合成(注意是有 GPU 合成,而不是只有 GPU 合成),0 表示本次合成没有 GPU 合成。

出现时机

SurfaceFlinger::doComposition() 的开头。

解释

SurfaceFlinger 按照合成的硬件不一样,有两种类型:

  • CLIENT 合成 又称为 GPU 合成,通过 CompositionEngine 调用一系列的 OpenGL ES 接口去完成合成的操作。

  • DEVICE 合成 又称为 HWC 合成,这种合成方式是使用 Hardware Composer 来进行合成。Hardware Composer 是一种特殊的硬件,在高通平台曾用名为 SDE,现在称为 DPU。 利用 Hardware Composer 来合成有其优势,例如省电,这个可能是它最大的优势了;不过劣势也是有的,例如:

  • 在某些场景下是无法进行 DEVICE 合成 例如 Layer 是圆角的,Layer 的总数超过硬件的上限等。

  • 合成逻辑和策略基本上都是 vendor 的闭源实现 由于策略闭源,如果出现问题只能依赖 vendor 去解决,不方便调试。

作用

我们说了 DEVICE 合成相对于 GPU 合成来说的优势是省电,那么如果发现了本应该是 DEVICE 合成的场景出现了 hasClientComposition 等于 1 的情况,那么就说明合成策略有问题,或许就可以解决一些功耗问题。

FrameMissed/GpuFrameMissed/HwcFrameMissed

FrameMissed
FrameMissed

值类型

布尔值,1 表示上一次的合成有对应的 FrameMissed 类型,0 表示没有。

出现时机

SurfaceFlinger 合成 Invalidate 阶段的最开始。

解释

FrameMissed/GpuFrameMissed/HwcFrameMissed 代表的是 SurfaceFlinger 上一次合成的结果,我们在 fps 的计算原理 中提到,当 SurfaceFlinger 合成完的帧显示到屏幕上时,present fence 就会 signal。因此 可以认为 present fence signal 相当于一次合成的彻底完成。

因此,SurfaceFlinger 在每一次开始被 VSYNC-sf 唤醒的时候,会先检查上次合成的情况,方式就是检查上一次合成的 present fence 有没有 signal。如果没有那么就认为是一个 FrameMissed,并且依据上一次合成的方式是否有 GPU 或者是 HWC 参与,对 GpuFrameMissedHwcFrameMissed 进行置位。

作用

present fence 没有及时 signal 主要有两种原因:

  1. Display 出问题了。
  2. App/游戏的 GPU 负载太高了,导致底层大部分时间都花在了等 GPU 渲染工作完成,延后了 present fence 的 signal,从而导致 FrameMissed。

FrameMissed 目前在 Android 官方有两个作用:

  1. 统计。
  2. Android 官方有一个 debug 开关,可以在检测到上一帧有 FrameMissed 出现的时候,跳过本次的合成,留给底层更多的时间去显示。这个初衷是好的,不让底层过于繁忙,通过主动跳过合成来减缓底层的工作量。但是由于跳过合成就相当于主动丢帧,在某些场景下会导致到持续性的掉帧。因此这个开关一般是不会打开的。

VSYNC-sf/VSYNC-app

VSYNC-sf
VSYNC-sf

值类型

瞬时布尔值,变化的时候表示该时刻发出了 VSYNC-sf/VSYNC-app 软件信号。

出现时机/解释

DispSync 分发的时候,具体可以看 DispSync 详解 这篇文章,有详尽的分析。

作用

VSYNC-app 和 VSYNC-sf 作为 DispSync 两个分发,是应用渲染/SurfaceFlinger 合成的起点,也是我们分析一个 Systrace 一开始最应该看的地方。如果某一处 VSYNC-sf 没有了,那么就说明该处有丢帧的情况,要么是 SurfaceFlinger 主动丢帧(如前面提到的);要么是 app 没有及时渲染完导致的丢帧。

小问题

(公众号最近在灰度问答的功能,很遗憾我没有被灰度到。)这里留一个思考题给大家思考一下:

VSYNC-sf/VSYNC-app 上的 Systrace 里,VSYNC-app 基本上没有什么变化,有可能是什么原因?

思考一下,欢迎大家在评论区留言讨论,下期 simowce 黑板报我将给出答案。或者大家对 Systrace 有哪些想要了解的内容,也欢迎大家在评论区留言。

尾巴

我在之前的文章说过,我写的文章都是我不懂且感兴趣的内容,但是这样会导致到我更新频率非常慢。我希望有一个更新频率更快的内容板块。我之前常在一些群里回答大家的疑问,然后渐渐地我发现很多问题被问了一遍又一遍,说明这些问题很有代表性,所以我希望能够总结起来,方便大家查阅。

而这不由得让我想起了小学六年级的时候,语文老师会每天在一块小黑板里写一道题,称之为“每日一题”,内容一般为一些往年的高频题或者是一些趣味题。感兴趣的同学可以写完单独找老师批改。我记得当时我抄了整整一本“每日一题”,自觉趣味无穷。

因此我给这个新的栏目起名为 “simowce 黑板报”,以此致敬一下我小学六年级的语文老师,顺便缅怀一下我的青春。

好了,这一期的 “simowce 黑板报” 到这里就结束了,如果你想第一时间看到 ”simowce 黑板报“ 的更新,请将这个公众号**”设为星标“。如果你觉得这篇文章写得还不错,求赞赏求点赞求在看,最重要的是点一个大大的关注**。各位的支持就是我更新的最大动力。

我们下期 ”simowce 黑板报“ 再见。

🏆 掘金技术征文|双节特别篇