当前位置: 首页 > news >正文

【性能优化】--perfetto分析思路

这里写目录标题

  • 目录
      • **一、一帧完整绘制的关键阶段**
      • **二、在 Perfetto 中搜索关键事件与函数**
        • **1. 应用进程(App)的绘制阶段**
        • **2. 缓冲区提交阶段**
        • **3. SurfaceFlinger 合成阶段**
        • **4. 显示刷新阶段**
      • **三、具体分析步骤**
        • **1. 定位目标时间段**
        • **2. 找到“一帧的起点”:Choreographer.doFrame**
        • **3. 追踪应用绘制链路**
        • **4. 追踪 SurfaceFlinger 合成链路**
        • **5. 确认帧显示完成:VSYNC 与显示事件**
        • **6. 分析瓶颈**
      • **四、实用工具与技巧**
      • 送显的核心作用
      • 送显的关键环节
      • 送显在 Perfetto 中的分析关注点
      • **一、先确定卡顿类型:按“帧耗时超标原因”分类**
      • **二、分析切入点:从“帧链路关键节点”定位卡顿阶段**
        • **1. 第一步:找到卡顿帧,确定总耗时**
        • **2. 第二步:按卡顿类型定位切入点**
          • **(1)应用绘制卡顿:从应用主线程的“耗时操作”切入**
          • **(2)合成卡顿:从 SurfaceFlinger 的“图层处理”切入**
          • **(3)送显卡顿:从“VSYNC 对齐”和“缓冲区”切入**
          • **(4)系统资源卡顿:从“线程阻塞”和“CPU 调度”切入**
      • **三、实战技巧:快速缩小范围**
      • **总结**

目录

在 Perfetto 中分析“一帧完整绘制过程”时,核心是追踪从应用发起绘制请求屏幕最终渲染的全链路,涉及 Android 系统的三大核心组件:应用进程(App)SurfaceFlinger(合成服务)显示硬件(如 GPU、屏幕刷新)。以下是具体分析方法:

一、一帧完整绘制的关键阶段

正常情况下,一帧的完整流程包含 4 个核心步骤(简称“渲染流水线”):

  1. 应用绘制(App Draw):应用进程通过 Canvas 或 OpenGL/ Vulkan 绘制 UI 元素(如 View 布局、自定义绘制)。
  2. 提交缓冲区(Buffer Queue):应用将绘制结果(图形缓冲区)提交到 SurfaceFlinger 的 BufferQueue。
  3. 合成(Compose):SurfaceFlinger 接收多个应用的缓冲区,进行图层合成(如叠加、透明度处理)。
  4. 显示(Present):合成结果发送到显示硬件(如通过 HWC 硬件合成),最终在屏幕上刷新显示。

这一过程需匹配屏幕刷新率(如 60Hz 对应每帧约 16.6ms),超过该时间会导致卡顿。

二、在 Perfetto 中搜索关键事件与函数

需通过过滤以下事件类型函数/进程名,定位一帧的完整链路:

1. 应用进程(App)的绘制阶段
  • 核心进程:目标应用进程(如 com.example.myapp)。
  • 关键事件/函数
    • Choreographer#doFrame:系统向应用发送的帧回调(触发应用开始绘制),是一帧的起点。
      • 搜索关键词:Choreographer.doFrameandroid.animation.Choreographer.doFrame
    • ViewRootImpl#performTraversals:应用执行测量(measure)、布局(layout)、绘制(draw)的入口。
      • 搜索关键词:ViewRootImpl.performTraversals
    • Canvas.draw*:应用通过 Canvas 绘制的具体操作(如 drawRectdrawText)。
    • OpenGL/Vulkan 调用:若使用硬件加速,会有 glDrawArraysvkQueueSubmit 等 GPU 绘制函数。
2. 缓冲区提交阶段
  • 核心进程:应用进程 + surfaceflinger 进程。
  • 关键事件/函数
    • Surface#queueBuffer:应用将绘制完成的缓冲区提交给 BufferQueue。
      • 搜索关键词:Surface.queueBufferandroid.view.Surface.queueBuffer
    • BufferQueueProducer#queueBuffer:BufferQueue 接收应用提交的缓冲区(SurfaceFlinger 侧)。
3. SurfaceFlinger 合成阶段
  • 核心进程surfaceflinger(系统合成服务)。
  • 关键事件/函数
    • SurfaceFlinger::onMessageInvalidate:SurfaceFlinger 收到缓冲区更新,触发合成。
    • SurfaceFlinger::commit:执行图层合成(软件合成或硬件合成)。
    • HWComposer::presentDisplay:若使用硬件合成(HWC),将合成结果提交给显示硬件。
4. 显示刷新阶段
  • 核心事件
    • vsync:垂直同步信号(屏幕刷新的时间基准),每帧一次,由硬件触发。
      • 搜索关键词:vsyncVSYNC(通常在 ftrace 事件中以 vsync-appvsync-sf 区分应用侧和 SurfaceFlinger 侧的 VSYNC)。
    • display_hw 相关事件:显示硬件的刷新完成事件(如 hwc_commit)。

三、具体分析步骤

以“分析某应用的一帧绘制流程”为例:

1. 定位目标时间段
  • 加载包含应用交互的 trace 文件(如滑动页面时的追踪)。
  • 在左侧 Processes 中展开目标应用进程(如 com.example.myapp)和 surfaceflinger 进程,显示其线程活动。
2. 找到“一帧的起点”:Choreographer.doFrame
  • 在顶部搜索框输入 Choreographer.doFrame,主视图会高亮所有应用侧的帧回调事件。
  • 点击某一个 doFrame 事件块,右侧详情面板会显示其开始时间(如 t=1000ms)和线程(通常是应用的 main 线程)。
3. 追踪应用绘制链路
  • doFrame 开始,在应用 main 线程的时间轴上,向后查找:
    • 若出现 ViewRootImpl.performTraversals 事件,说明进入测量、布局、绘制阶段。
    • 后续若有 Canvas.draw*glDrawArrays 等事件,对应具体绘制操作。
    • 绘制结束后,会出现 Surface.queueBuffer 事件,标志应用提交缓冲区完成(记录此时时间 t1)。
4. 追踪 SurfaceFlinger 合成链路
  • 切换到 surfaceflinger 进程的线程(通常是 main 线程),查找 BufferQueueProducer.queueBuffer 事件(对应应用提交的缓冲区到达 SurfaceFlinger,时间 t2)。
  • 后续会出现 SurfaceFlinger.commitHWComposer.presentDisplay 事件,标志合成完成(时间 t3)。
5. 确认帧显示完成:VSYNC 与显示事件
  • 在左侧 CPUsEvents 中查找 vsync 事件,合成完成后下一个 vsync 信号会触发屏幕刷新(时间 t4)。
  • 一帧的总耗时为 t4 - t0t0 为上一帧的 vsync 时间),若超过 16.6ms(60Hz)则可能卡顿。
6. 分析瓶颈
  • 应用绘制耗时过长:若 performTraversalsqueueBuffer 时间过长(如 >10ms),说明应用布局复杂或绘制逻辑低效(需优化 View 层级、减少过度绘制)。
  • 合成耗时过长surfaceflingercommitpresentDisplay 时间过长,可能是图层过多或硬件合成能力不足(需减少图层、使用 SurfaceControl 优化)。
  • VSYNC 对齐问题:若帧提交时间错过 VSYNC 信号,会导致多等待一帧(如本应 16ms 显示,实际 32ms),需检查应用是否及时响应 doFrame

四、实用工具与技巧

  1. 使用“Frame Timeline”视图
    若 trace 包含 android.frame_timeline 数据源(需在配置中添加),左侧会出现 Frame Timeline 追踪项,直接显示每帧的开始/结束时间、总耗时及各阶段分解(如 AppSFPresent 耗时),一目了然。

  2. 通过 SQL 统计帧耗时
    在 Perfetto 的 SQL 编辑器中执行以下查询,统计应用每帧的总耗时:

    SELECTts / 1e6 AS start_ms,  -- 帧开始时间(毫秒)dur / 1e6 AS frame_duration_ms,  -- 帧总耗时(毫秒)package  -- 应用包名
    FROM android_frame_timeline_slice
    WHERE package = 'com.example.myapp'
    ORDER BY start_ms;
    

    frame_duration_ms 频繁 >16.6,则存在卡顿。

  3. 对比正常帧与卡顿帧
    找到耗时正常的帧(如 10ms)和卡顿帧(如 30ms),对比两者在应用绘制、合成阶段的事件差异,定位卡顿帧中额外的耗时操作(如突然出现的大对象绘制、锁等待)。

通过以上方法,可清晰拆解一帧的完整流程,并定位各阶段的性能瓶颈。核心是抓住 Choreographer.doFrame(起点)、queueBuffer(应用提交)、SurfaceFlinger 合成、VSYNC(显示)这几个关键节点,结合时间差分析耗时。

送显
在 Android 性能分析(尤其是图形渲染和帧显示流程)中,“送显” 是指将最终合成的图像数据提交给显示硬件(如屏幕、显示屏控制器),并由硬件完成实际像素刷新的过程,是一帧画面从“系统处理完成”到“用户可见”的最后一步。

送显的核心作用

在帧渲染的全链路中,应用进程完成绘制、SurfaceFlinger 完成图层合成后,得到的是一帧完整的图像数据(通常存储在图形缓冲区中)。送显就是将这一缓冲区的数据“交付”给显示硬件,触发屏幕的物理刷新,让用户看到这一帧画面。

送显的关键环节

  1. 合成结果提交
    SurfaceFlinger 完成图层合成后(无论是软件合成还是硬件合成 HWC),会将最终的图像缓冲区通过 HWComposer(硬件合成器) 提交给显示控制器(Display Controller)。

    • 对应关键事件:HWComposer::presentDisplay(Perfetto 中可搜索该函数名追踪)。
  2. 显示硬件刷新
    显示控制器接收到缓冲区后,会等待下一个 VSYNC(垂直同步信号),在信号触发时将缓冲区数据发送到屏幕的物理像素,完成实际显示。

    • VSYNC 是屏幕刷新的时间基准(如 60Hz 屏幕每 16.6ms 一次),确保画面刷新与屏幕扫描节奏一致,避免画面撕裂。

送显在 Perfetto 中的分析关注点

  • 送显时机:通过搜索 vsync 事件和 presentDisplay 事件,查看合成完成到送显的时间间隔。若间隔过长,可能导致帧显示延迟(错过 VSYNC 信号,需多等待一帧)。
  • 送显成功率:若频繁出现 hwc_commit_failed 等事件,可能是硬件合成失败或缓冲区异常,导致画面卡顿或闪烁。
  • 送显耗时:正常情况下送显应在 1-2ms 内完成,若耗时过长(如超过 5ms),可能是显示硬件性能不足或驱动问题。

简言之,“送显”是连接系统图形处理与用户视觉感知的最后一步,直接影响帧显示的及时性和流畅度。

在 Perfetto 的 trace 中分析卡顿问题时,核心是先通过帧耗时判断卡顿类型,再定位卡顿发生的阶段(应用绘制、合成、送显等),最后聚焦具体函数或事件作为切入点深入分析。以下是具体方法:

一、先确定卡顿类型:按“帧耗时超标原因”分类

卡顿的本质是单帧耗时超过屏幕刷新率对应的阈值(如 60Hz 屏幕单帧应 ≤16.6ms,90Hz 应 ≤11.1ms)。根据卡顿发生的环节,可分为以下几类:

卡顿类型核心特征(Perfetto 中表现)常见原因
应用绘制卡顿应用进程(如 com.example.app)的 main 线程耗时过长(doFramequeueBuffer 阶段 >10ms)布局复杂、过度绘制、主线程做耗时操作(如 IO、大量计算)、自定义 View 绘制低效等。
合成卡顿SurfaceFlinger 进程(surfaceflinger)的合成阶段耗时过长(queueBufferpresentDisplay 阶段 >5ms)图层过多(>4 层)、硬件合成(HWC)失败降级为软件合成、图层格式不兼容导致额外转换等。
送显卡顿合成完成到屏幕显示的时间间隔过长(错过 VSYNC 信号,导致多等待一帧)合成完成时间晚于 VSYNC 信号、显示硬件(如 GPU、显示屏控制器)响应慢、缓冲区争夺等。
系统资源卡顿应用或 SurfaceFlinger 线程被阻塞(如锁等待、CPU 资源被抢占),导致无法及时处理帧任务其他进程占用过高 CPU(如后台进程频繁唤醒)、线程优先级低被抢占、锁竞争(如 synchronized 阻塞)等。

二、分析切入点:从“帧链路关键节点”定位卡顿阶段

1. 第一步:找到卡顿帧,确定总耗时
  • 通过 Frame Timeline 快速定位(推荐):
    若 trace 包含 android.frame_timeline 数据源(配置时需添加),左侧 Frame Timeline 追踪项会直接显示每帧的:

    • 总耗时(Duration):若超过 16.6ms(60Hz),即为卡顿帧。
    • 各阶段耗时分解:App(应用绘制)、SF(SurfaceFlinger 合成)、Present(送显)。
      例如:某帧 App 耗时 20ms,SF 耗时 3ms,Present 耗时 1ms → 确定为应用绘制卡顿
  • 手动追踪帧链路(无 Frame Timeline 时):
    Choreographer.doFrame(应用帧起点)为基准,到下一个 VSYNC 信号(显示终点)的时间差即为单帧耗时。若超过阈值,标记为卡顿帧。

2. 第二步:按卡顿类型定位切入点
(1)应用绘制卡顿:从应用主线程的“耗时操作”切入
  • 核心追踪目标:应用 main 线程的 doFrameperformTraversalsqueueBuffer 链路。
  • 切入点操作
    1. 在卡顿帧的 doFrame 事件后,查看应用 main 线程的时间轴,找到持续时间长的函数块(超过 5ms 的事件)。
    2. 重点搜索以下关键词,定位具体耗时操作:
      • ViewRootImpl.performTraversals:若耗时过长(如 >8ms),说明测量(measure)、布局(layout)、绘制(draw)阶段有问题。
        • 展开该事件,查看子事件:measure 耗时高 → 布局层级过深或 onMeasure 逻辑复杂;draw 耗时高 → 过度绘制或 onDraw 中做耗时计算。
      • Canvas.draw*glDrawArrays:若某绘制函数(如 drawBitmap)耗时过长 → 图片过大或绘制频繁。
      • Handler.dispatchMessageRunnable.run:若主线程执行了非 UI 操作(如 new Thread 意外在主线程运行)→ 阻塞绘制。
      • Binder.call:若主线程频繁调用 Binder(如跨进程通信)→ IPC 耗时阻塞绘制。
(2)合成卡顿:从 SurfaceFlinger 的“图层处理”切入
  • 核心追踪目标surfaceflinger 进程的 main 线程(合成主线程)或 RenderEngine 线程(软件合成)。
  • 切入点操作
    1. 查看卡顿帧中 surfaceflingerqueueBuffer(接收应用缓冲区)到 presentDisplay(提交给硬件)的时间差,若 >5ms 则为合成卡顿。
    2. 重点搜索以下关键词:
      • SurfaceFlinger::commit:若耗时过长 → 图层合成逻辑复杂,可进一步查看是否有 SoftwareComposer 相关事件(说明硬件合成失败,降级为软件合成,耗时更高)。
      • Layer::prepareLayer::composite:若某图层处理耗时高 → 该图层可能过大(如全屏图层)、格式不兼容(如 YUV 转 RGB)或有透明度过高(需混合计算)。
      • HWComposer::validateDisplay:若耗时高 → 硬件合成器(HWC)处理图层时出现瓶颈,可能是图层数量超过硬件限制(如超过 4 层)。
(3)送显卡顿:从“VSYNC 对齐”和“缓冲区”切入
  • 核心追踪目标vsync 信号、presentDisplay 事件、BufferQueue 状态。
  • 切入点操作
    1. 查看合成完成时间(presentDisplayts)与下一个 vsync 信号的时间差:
      • 若合成完成时间在 vsync 信号之后 → 错过本次刷新,需等待下一帧(多 16.6ms),属于送显延迟
    2. 搜索 buffer_queue 相关事件:
      • 若出现 dequeueBuffer blocked(申请缓冲区阻塞)→ 应用或 SurfaceFlinger 缓冲区不足(如未及时释放),导致送显等待。
      • acquireBuffer 耗时过长 → SurfaceFlinger 获取应用缓冲区延迟,可能是缓冲区被占用(如应用未及时提交)。
(4)系统资源卡顿:从“线程阻塞”和“CPU 调度”切入
  • 核心追踪目标:应用/surfaceflinger 线程的状态(如 Running/Sleeping/Uninterruptible)、CPU 核心负载、锁事件。
  • 切入点操作
    1. 查看卡顿帧期间,应用 main 线程或 surfaceflinger 线程是否频繁处于 SleepingUninterruptible 状态:
      • Sleeping 时间长 → 可能被低优先级线程抢占,或等待锁(如 synchronized 锁被其他线程持有)。
      • 搜索 sched_switch 事件:查看线程被切换出去的原因(prev_state=S 表示休眠),以及切换进来的线程(是否被高优先级线程抢占)。
    2. 查看 CPU 核心负载(左侧 CPUs 展开各核心):
      • 若某核心长期 100% 占用(绿色块填满时间轴)→ 可能是其他进程(如后台服务)占用过多 CPU,导致应用线程无法调度。
      • 搜索进程名:通过顶部搜索框查找高 CPU 占用的进程(如 com.android.systemui 异常活跃)。

三、实战技巧:快速缩小范围

  1. 对比正常帧与卡顿帧
    找到同一操作下的正常帧(如 10ms)和卡顿帧(如 30ms),对比两者在应用绘制、合成、CPU 调度上的差异。例如:卡顿帧中多了一个 onDraw 耗时 20ms 的事件 → 切入点就是该 onDraw 函数。

  2. 利用 SQL 统计耗时TOP事件
    在 Perfetto 的 SQL 编辑器中执行查询,定位应用主线程中耗时最长的函数:

    SELECTname,  -- 函数名SUM(dur) / 1e6 AS total_ms,  -- 总耗时(ms)COUNT(*) AS count  -- 调用次数
    FROM slice
    WHERE utid IN (SELECT utid FROM thread WHERE name = 'main' AND process.name = 'com.example.app')
    GROUP BY name
    ORDER BY total_ms DESC
    LIMIT 10;
    

    结果中排名靠前的函数(如 View.draw)即为重点分析对象。

  3. 结合日志定位场景
    若 trace 包含 android.log 数据源,可通过搜索应用日志(如 D/MyApp: 开始滑动)定位卡顿发生的业务场景(如滑动列表、弹窗显示),再聚焦该场景下的帧链路。

总结

  1. 先通过 Frame Timeline 或帧链路确定卡顿帧的总耗时及各阶段占比,划分卡顿类型(应用/合成/送显/资源)。
  2. 针对不同类型,聚焦对应进程(应用/surfaceflinger)和线程(main 线程/合成线程)。
  3. 搜索关键函数(如 performTraversalscommit)或事件(vsyncsched_switch),找到耗时最长的操作作为切入点,逐步拆解具体代码或逻辑问题。

通过这种“定位类型→聚焦阶段→拆解操作”的流程,可高效定位卡顿根源。

http://www.dtcms.com/a/516448.html

相关文章:

  • **发散创新:探索生物神经网络与编程语言的交融**随着生物神经网络研
  • 平台网站开发公司广州安全教育平台登陆
  • 第1章:初识Linux系统——第8节:查看/修改权限控制和ACL
  • Rust所有权机制在Web服务开发中的避坑指南
  • 成都网站开发费用企业网站建设任务书
  • pyhton 螺旋矩阵(指针-矩阵-中等)含源码(二十六)
  • 矩阵的奇异值分解(SVD)在三维图形学中的进阶应用
  • 装饰器加强
  • 17Z一起做网站广州站南阳商都网站做网站
  • MySQL多实例部署实战指南
  • 微网站建设招聘做招聘网站代理商需要多少钱
  • Android 网络变动监听
  • Deep Metric Learning(深度度量学习)
  • 消息队列RabbitMQ、Kafka、ActiveMQ 、Redis、 ZeroMQ、Apache Pulsar对比和如何使用
  • 建网站专用网站标准物质网站建设模板
  • (四)Flutter插件之IOS插件开发
  • 湘潭网站建设 x磐石网络广州网站建设培训学校
  • 织梦做的网站老是被黑国外做美食视频网站有哪些
  • 自动化测试相关使用
  • 做移门图的 网站有哪些做招聘网站需要做什么公司
  • TDengine 数字函数 RADIANS 用户手册
  • 做导航网站赚钱企业网站搜索优化外
  • 网站网页设计公司海南省建设执业中心网站
  • 如何解压一个MacOs PKG 安装包修改内容后重新打包
  • Linux 与 Windows:谁更适合 CLI 模式 AI 编程工具?
  • 深度学习(15)-PyTorch torch.nn 参考手册
  • 人工智能Pytorch开发环境的搭建
  • 【研究生随笔】Pytorch中的多层感知机
  • 广州知名网站建设性价比高三乡网站建设公司
  • 网站的建设流程图跨境电子商务网站建设