Flutter 页面打开速度优化

Flutter Engine 调优系列 (一) – Flutter 页面打开速度优化

在给 flutter engine 进行调优定制过程当中,我们针对 flutter 进行了一系列的改良,也拓展了一些原有的基础建设(包括 flutter apm 体系flutter monkey 测试 等),这篇文章将会介绍一下 flutter 页面打开速度优化 的调研过程和方案,并且由此开发的 线上 trace系统 也希望能给后续类似需求提供一些经验和方向。

打开速度埋点

  • 起始时间

点击 flutter 页面的入口按钮

  • 结束时间

gpu 第一帧渲染完成

未优化之前的线上数据

机型 90 分位耗时 (毫秒)
iPhone 6 Plus 2510

线上数据非常出乎意料,iPhone 6 Plus 的表现竟然如此糟糕,90 分位耗时达到 2510 毫秒,这个指标需要得到改善,针对这个问题我们开始展开调研。

线下调研

我们找来一台 iPhone 6 Plus 设备,手动测试过程当中观察了一下埋点数据,发现数据并没有 2510 毫秒那么差,线下测试 100 - 500 毫秒的数据都有出现过,我们接着再细分了一些线上数据的分布,得到结果如下:

机型 0 -> 500 毫秒 500 -> 1000 毫秒 1000 -> 2000 毫秒 > 2000 毫秒
iPhone 6 Plus 48.9 % 15.1 % 15.3 % 20.7 %

看来只凭开发在本地测试有可能找不到线上用户真正发生的瓶颈,我们需要一种手段去了解线上用户在打开 flutter 页面过程当中耗时瓶颈是什么。

线上策略

我们希望能够精准的定位耗时瓶颈,所以需要实现一套类似于 xcode instruments time profiler 的功能,但是 xcode instruments time profiler 还不是很直观,其实 android 的 trace view 功能是我们想要的功能,能够直观的分析整个运行过程的调用时序,以及耗时过长的函数,所以 trace view 也常常用于卡顿,启动分析等场景,为此,我们开发了 ios 版的 线上 trace 功能。

最终的 trace view 效果如下图所示:

trace_ios

ios trace 实现原理

  • 客户端堆栈聚合上报

当 trace 功能开启的时候会激活采样线程,采样线程以 100 毫秒的频率去捕获所有的线程堆栈,trace 功能关闭的时候会将之前的堆栈进行聚合上报,采样聚合过程如下:

第一次采样的调用链

A -> B -> C

第二次采样的调用链

A -> B -> D

合并后的调用链

A (2) -> B (2) -> C(1), D(1)

有了整个调用链的层级、以及频率信息之后,则可以生成 trace view 树进行展示。

  • 服务器聚类 && 生成 trace view 树

根据客户端上报的调用链信息,从中提取频率 > 50% 的栈顶函数作为聚类信息,这样可以将类似的调用链聚合在一起。

比如: A (2) -> B (2) -> C(1), D(1) 这个调用链就可以提取 B (2) 作为聚类信息。

分析线上 trace view

我们针对 点击 flutter 页面入口按钮 到 gpu 第一帧渲染完成 这一过程开启了 trace 的功能,并且对这一过程 > 2000 毫秒的数据进行上报,经过服务器聚类之后,大部分 trace view 瓶颈如下图所示:

flutter_page_open

进入 flutter 页面的时候会进行 engine 的创建,flutter::shell::create 会等待 flutter ui 线程将 dart vm 以及 dart isolate 创建完成,而瓶颈点是在创建 dart isolate 这一过程当中,flutter::DartIsolate::CreateRootIsolate 的执行耗时高达 1300 毫秒,这一步的发现为后续提供优化方案 提供了非常重要的方向和线索

dart isolate 的创建涉及到大量的 io 操作,即使是同一款机型,在不同的运行状态下也会有不同的表现,所以线上的数据会有呈现出一种分布,在线下测试过程当中也不容易复现,我们决定将 dart isolate 放在异步线程当中进行预加载,这种方案不需要初始化 engine 的其他部分,比如:opengl相关的视图缓存,内存占用会更少,并且可以进行异步化避免卡顿 (官方 engine 本身是只能在主线程进行初始化的)。

优化方案效果

机型 90 分位耗时 (毫秒)
iPhone 6 Plus 1169

更多

这套 trace 系统能够方便的获取线上 app 的运行状态,给优化工作提供了具有极大意义的参考,在线下自动化测试我们也提供了更高精度,更强大的 trace 功能,用于启动耗时分析,页面打开分析,以及 逆向系统库和第三方应用 等多个领域,希望能给大家带来这方面的参考。