上一篇文章,我们了解了Impeller在渲染方面的优势以及整个渲染流程,接下来我将通过实际实验来测试下Skia与Impeller在渲染性能上的优劣。
我编写了一段自定义Canvas动画绘制的代码,在屏幕上绘制一个圆形,并在随机位置产生气泡,以模拟复杂UI动画场景。效果如下图所示:

该动画运行一段时间以收集足够帧数据。我们分别在Impeller 和 Skia 渲染器下运行此应用,并记录性能数据。
我使用的设备是Pixel 8 pro,得到的渲染数据如下: 使用skia的渲染表现:

使用Impeller的渲染表现:

同时我下载了devtool的相关数据,并编写了python脚本,对数据进行了分析,得到了如下表格:
指标 | Impeller 渲染 | Skia 渲染 |
---|---|---|
UI线程帧构建平均耗时 (ms) | 2.10 | 2.07 |
UI线程帧构建 95th 百分位 耗时 (ms) | 3.45 | 3.48 |
GPU线程光栅绘制平均耗时 (ms) | 2.81 | 4.05 |
GPU线程光栅绘制 95th 百分位 耗时 (ms) | 4.00 | 5.55 |
每帧总耗时平均值 (ms) | 6.57 | 7.71 |
每帧总耗时 95th 百分位 (ms) | 8.74 | 10.24 |
帧在8.33ms内完成渲染比例 (%) (120Hz帧率要求) | 91.6% | 67.1% |
帧耗时超过16.67ms比例 (%) (低于60fps的掉帧) | 0.29% | 0.09% |
可以看到,Impeller 相比 Skia 在 GPU 渲染阶段有明显优势:平均每帧 GPU 绘制耗时降低约30%(2.81ms vs 4.05ms),95th百分位耗时降低约1.5ms。这意味着大部分帧Impeller的GPU线程负担更小,帧渲染更快。而UI线程帧建构时间两者基本相当,平均约2ms,说明更换渲染器对框架层的布局建树开销几乎无影响。
在总帧时间上,Impeller 模式平均每帧约6.57ms,Skia约7.71ms;结合120Hz刷新率8.33ms的预算,Impeller 大多数帧都能赶在下一次VSync前完成。如上表所示,在Impeller下有高达91.6%的帧耗时不超过8.33ms,可以实现接近120fps的流畅度,而 Skia 下这一比例只有约67.1%。换言之,Skia 渲染有约三分之一帧未能在120Hz间隔内完成(这些帧通常耗时落在8~12ms之间),需要等到下一个刷新周期才显示出来,等效帧率跌至60--120fps之间。Impeller 因为减少了 GPU 卡顿,在相同动画下绝大部分帧都达到了120fps要求。两者在超过16.67ms(低于60fps的明显掉帧)情况都很少,测试中Skia仅有~0.09%帧、Impeller约0.29%帧超过16.67ms,不过Impeller的几次超时是集中在首次创建管线的少数帧,上文平均数已平滑了这类一次性开销。
上述统计和图表反映出 Impeller 的总体性能优势:更低的平均帧渲染时间和更少的帧延迟抖动。接下来我们深入各类性能事件,逐项分析差异来源。

-
UI线程帧建构(UI::Frame)
首先是 UI 线程的帧构建阶段。UI线程主要执行框架的 build/layout 等操作,性能取决于UI结构和代码逻辑,本身不受渲染后端影响。因此切换 Impeller 不会影响 Dart 层UI布局构建效率,这一点从数据中得到验证。值得注意的是,我在 Skia 模式下捕获到一帧异常的 UI 构建耗时(约39.8ms),远高于正常水平,导致该帧总耗时达47ms。这可能由于偶发的垃圾回收或极端情况(与渲染器关系不大),Impeller 跑相同场景并未发生类似的异常。这提醒我们在分析时应关注整体趋势而非个别异常帧。总的来说,两种引擎的 UI 线程开销可以视为持平。
不过,UI线程也可能受到 GPU 线程速度的间接影响:如果 GPU 无法及时处理上一帧,UI线程在 produce 新帧时可能阻塞等待(即 PipelineProduce 延迟)。这一情况常发生于连续多帧超时导致 pipeline 队列积压。在我收集到的数据中,Skia 有一些帧表现出 UI构建完成很快但总帧耗时接近两倍刷新间隔的情况,这表示UI曾等待 GPU 空闲。而 Impeller 由于 GPU 更快,极少出现此等待。后文Pipeline部分详述。
2. GPU线程光栅绘制(Rasterizer::Draw)
GPU线程的表现是 Impeller 相对 Skia 差异最大的部分。Rasterizer::Draw 事件表示 GPU 线程将 UI线程提交的layer树光栅化为屏幕图像的过程。在 Skia 中,Rasterizer 绘制每帧平均耗时约4.05ms,中位数比 Skia 快了约1.4ms。这种大幅提升说明 Impeller 针对 GPU 渲染执行做了优化。一方面,Impeller 的渲染实现利用现代图形API更高效,例如可能通过批处理减少驱动开销、利用并发等手段,让同样的绘制工作耗时更短。另一方面,没有插入运行时的 shader 编译步骤,也避免了 GPU线程的突然卡顿。
值得强调的是,Skia 渲染中 GPU 耗时出现了一些明显的波动和尖峰,例如我们观察到 Skia 有多帧Rasterizer耗时达到912ms,远超平常。这往往对应着Shader JIT 编译过程。
不过Impeller 虽然没有运行时 shader 编译,但并非完全没有一次性开销。在我们的Impeller追踪数据中,出现了 PipelineVK::Create 等事件------这是 Impeller 为特定渲染操作创建GPU管线状态的过程(对应第一次使用某类渲染管线,例如第一次绘制某种组合的Shader/Blend模式)。这些事件一般也只在首次发生,Impeller会将结果缓存供后续使用。大多数 Pipeline 创建非常快,未对帧率造成影响,但我观察到有两次管线创建使得当帧 GPU 耗时激增:一次耗时约17ms(帧28),另一次约35ms(帧178),分别导致这两帧总时间达到20ms和40ms,出现明显卡顿。推测第一次发生在动画初始时,Impeller需要创建一批基础管线;第二次可能是动画过程中引入了新的绘制效果触发新的管线创建。这些 一次性的长耗时 构成了Impeller帧耗时分布的"长尾",也是上文统计中Impeller极少数帧超过16ms的原因。不过,这与Skia频繁的小幅卡顿有本质不同------Impeller的管线创建只在首次出现,属于可预见且可避免的开销(例如可在应用初始化或闲时预先触发这些绘制来完成管线创建),而 Skia 的 JIT shader 编译则难以完全预测,可能在应用运行过程中的任何新场景触发。
3. PipelineProduce 阶段与帧同步

PipelineProduce 是 Flutter 框架将 UI线程构建的场景提交给 GPU线程处理的过程。如果 GPU线程滞后于UI线程,那么UI在这个阶段可能被阻塞等待。通过分析 SceneDisplayLag 事件和帧间隔,我们可以了解掉帧与管线阻塞情况。我的统计显示,在相近时长的采样中,Skia 模式触发了 29 次 SceneDisplayLag(帧未及时显示的延迟事件),而 Impeller 仅有 12 次,Skia 出现帧滞后的频率约为 Impeller 的2.4倍。这与之前帧在8ms内完成的比例吻合:Skia 更频繁地错过目标 vsync,导致 pipeline 队列堆积,从而出现UI等待 GPU的情况。具体表现如前文提到的Skia某帧UI耗时极低但总时长接近两个帧间隔------意味着UI构建完成后等待了将近一个帧时间,直到GPU处理完前一帧才能继续。这就是一次 PipelineProduce 延迟导致的整帧延后。Impeller 因更少错过vsync,UI很少需要等待,PipelineProduce 几乎都是即时完成,保障了帧流水线的畅通。
4. 着色器编译与GPU事件
Shader 编译事件在两种引擎表现出明显差异:在 Skia Timeline 中我们发现了多处 Shader 相关编译记录(例如 Compiler::convertProgram 等),总计约14次,与我们的帧耗时尖峰一一对应。而 Impeller Timeline 中没有任何 runtime ShaderCompile 事件,验证了其预编译设计的效果。取而代之,Impeller 有几十次 PipelineVK::Create 事件,如上节所述,表示管线创建。值得一提,Impeller 这样设计实际上是将需要编译的 Shader 集合限定在一个较小范围,并在引擎构建时就全部编译好。Impeller默认支持Flutter核心绘制效果的预编译,但如果应用使用自定义Shader或某些特殊绘制(比如滤镜),Impeller 可能暂不支持或仍需要特殊处理。因此在开启 Impeller 后,应确认应用的绘制效果都正常且性能受益。如果有使用 Scene.toImage、旧版API等情况,需要关注Impeller支持度。
GPU 内存与并发: 从本次测试的性能数据来看,两种引擎在GPU占用和并发调度上的区别不易直接量化。但根据官方文档,Impeller 利用现代GPU API的优势,在需要时可以跨多线程并行执行GPU相关任务,并对资源生命周期进行更精细的控制。这在极端复杂场景下可能进一步提高吞吐。本测试的Canvas动画尚不足以体现Impeller在并发上的潜力,但其"可预测性能"的目标使它更适合那些需要稳定高帧率的场景,例如富动画界面、游戏等。
综合上述分析,Flutter Impeller 渲染引擎在我自定义Canvas动画测试中表现出优于 Skia 的渲染性能。Impeller 有效地消除了由于运行时着色器编译导致的帧率抖动,使帧时间更加稳定。对于动画复杂、图形效果丰富的应用,启用 Impeller 可以显著减少卡顿,带来更顺滑的用户体验。