Flutter 混合组合平台视图滚动性能基准测试:platform_views_layout_hybrid_composition 实战指南
本文围绕 Flutter 仓库中的 dev/benchmarks/platform_views_layout_hybrid_composition 基准工程,完整讲解两类设备端性能测量流程:使用 flutter drive --profile 运行平台视图列表滚动基准,以及在真机/模拟器上测量应用启动时间。读完后,你将掌握该基准工程的运行方式、输出文件位置与命名约定、驱动测试的滚动剧本与降噪技巧,并能从源码层面理解“混合组合”(hybrid composition)模式下 AndroidViewSurface 的创建链路和 devicelab CI 任务如何复用同一套基准。
基准工程是什么:混合组合模式下的平台视图滚动负载
该工程位于 dev/benchmarks/platform_views_layout_hybrid_composition,其 pubspec.yaml 中的描述点明了定位:
A benchmark for platform views, using hybrid composition on android.
也就是说,它专门测量在 Android 混合组合(hybrid composition / PlatformViewLink)模式下嵌入原生视图时的滚动性能。与同级的 platform_views_layout(虚拟纹理模式)基准不同,这里每个列表项都会把真实原生视图叠加到 Flutter 合成器之上,滚动压力来自原生视图的布局、绘制与 Flutter 层的交互叠加。
从 lib/main.dart 的源码结构看,负载由三部分组成:
- 一个 200 项的
ListView.builder,其滚动列表挂载在Key('platform-views-scroll')上,这个 key 是驱动测试定位滚动容器的锚点; - 每个列表项内嵌一个
DummyPlatformView(300×200 的原生视图占位),iOS 走UiKitView,Android 走本工程自定义的AndroidPlatformView; - 每个列表项还有一个
RotationContainer,即一个持续旋转的RotationTransition动画(_rotationController.repeat()),保证滚动期间 GPU 与渲染管线始终处于活跃状态,模拟真实应用中“边滚动边动画”的复合负载。
Android 侧的 AndroidPlatformView 实现见 lib/android_platform_view.dart:它通过 PlatformViewLink 组合 AndroidViewSurface(命中测试策略为 PlatformViewHitTestBehavior.opaque),并在 onCreatePlatformView 回调里调用 PlatformViewsService.initExpensiveAndroidView 创建原生视图。这正是“混合组合”路径的典型写法——原生视图作为独立 surface 合成,而不是纹理上传,也是该基准与 platform_views_layout(虚拟纹理)基准的核心区别。
滚动基准:命令、结果文件与命名约定
README 给出的标准运行方式是在工程目录下对设备执行:
flutter drive --profile test_driver/scroll_perf.dart
其中:
--profile保证以 profile 模式(AOT 编译、关闭断言)运行被测应用,这是性能测量的前提;test_driver/scroll_perf.dart是被测应用入口(需启用enableFlutterDriverExtension(),见 test_driver/android_view_scroll_perf.dart);- 实际滚动剧本由 test_driver/scroll_perf_test.dart 执行,通过
driver.connect()与设备端通信。
README 同时约定了两个结果文件的落盘位置:
| 文件 | 内容 |
|---|---|
build/platform_views_scroll_perf_hybrid_composition.timeline_summary.json |
汇总后的帧时间线(帧耗时、jank 等聚合指标) |
build/platform_views_scroll_perf_hybrid_composition.timeline.json |
完整详细时间线,用于逐帧深挖 |
文件名的由来可以在驱动测试源码中一一印证:testScrollPerf 里用 driver.traceAction 包裹滚动动作采集 Timeline,再经 TimelineSummary.summarize(timeline) 汇总并调用 summary.writeTimelineToFile(summaryName, pretty: true) 写出,其中 summaryName 正是 'platform_views_scroll_perf_hybrid_composition'。
驱动测试的滚动剧本与降噪设计
scroll_perf_test.dart 的测量剧本值得细读,其中几个细节直接决定数据质量:
- 250ms 初始延迟:注释说明这是为了避免在设备负载高峰期(如应用刚启动的后台活动)开始计时,否则基准噪声更大(关联 issue #19434);
driver.forceGC():在计时前强制一次 GC,排除 GC 停顿对帧时间的干扰;- 滚动动作:向下连续滚动 5 次,每次
driver.scroll(list, 0.0, -300.0, Duration(milliseconds: 300)),即 300ms 内位移 300 像素,动作之间间隔 500ms 冷却;随后再向上对称滚动 5 次,覆盖两个方向的布局/绘制路径; - 禁用帧同步:外层
driver.runUnsynchronized包裹了整个测试。原因是列表里存在持续旋转动画(来自main.dart的RotationContainer),若按帧同步,驱动会一直等待动画收敛而无法完成同步,因此必须改为非同步模式; - 测试超时设为
Timeout.none,因为真机上整套滚动流程耗时较长。
此外,按平台区分的驱动入口 test_driver/android_view_scroll_perf.dart 与 test_driver/uikit_view_scroll_perf.dart 内容一致(都是 enableFlutterDriverExtension() + 运行 PlatformViewApp),分别作为 Android 与 iOS 平台下 flutter drive 的应用端入口。
启动时间基准:--trace-startup 与 start_up_info.json
README 的第二部分给出了启动耗时测量方式:
flutter run --profile --trace-startup
说明:
--profile同样是 profile 模式前提;--trace-startup让引擎在启动阶段写入跟踪信息,启动阶段的关键时间点会打印到**运行日志(logs)**中;- 更结构化的附加结果写入
build/start_up_info.json,便于脚本化解析各启动阶段耗时。
适用前提是已连接真机或模拟器:flutter run 需要目标设备,且该工程需完成对应平台目录(android/ 与 ios/ 均已提供,含 DummyPlatformView 的原生实现,如 android/app/.../DummyPlatformViewFactory.java 与 ios/Runner/DummyPlatformView.m)的构建。
devicelab CI 中如何复用该基准
该基准并非只能手动执行。从 devicelab 任务定义 dev/devicelab/lib/tasks/perf_tests.dart 可以看到,CI 的 createAndroidViewScrollPerfTest 任务直接复用了同一工程与同一组文件:
TaskFunction createAndroidViewScrollPerfTest() {
return PerfTest(
'${flutterDirectory.path}/dev/benchmarks/platform_views_layout_hybrid_composition',
'test_driver/android_view_scroll_perf.dart',
'platform_views_scroll_perf_hybrid_composition',
testDriver: 'test_driver/scroll_perf_test.dart',
enableMergedPlatformThread: true,
).run;
}
三个字符串参数与手动流程一一对应:应用入口 test_driver/android_view_scroll_perf.dart、结果汇总名 platform_views_scroll_perf_hybrid_composition(即 timeline_summary.json 的前缀)、驱动脚本 test_driver/scroll_perf_test.dart。另外 enableMergedPlatformThread: true 表明 CI 在运行该基准时启用了合并平台线程开关,属于 CI 特定的运行时配置,手动复跑时可留意这一差异。
复跑与结果解读要点
综合 README 约定与源码,完整复跑流程可归纳为:
- 进入 dev/benchmarks/platform_views_layout_hybrid_composition 目录,连接 Android 或 iOS 设备;
- 执行
flutter drive --profile test_driver/scroll_perf.dart(Android 侧驱动入口亦可对照 CI 使用test_driver/android_view_scroll_perf.dart); - 打开
build/platform_views_scroll_perf_hybrid_composition.timeline_summary.json查看帧耗时汇总(重点看 janky frames 比例、P100/平均帧耗时);逐帧分析则使用同名.timeline.json; - 需要启动数据时,另跑
flutter run --profile --trace-startup,从日志与build/start_up_info.json读取启动阶段耗时。
需要注意的限制:该基准只覆盖 Android 混合组合与 iOS UIKit 两种平台路径(main.dart 中其他平台会触发 assert(false, 'Invalid platform'));结果会受设备型号、系统负载与是否启用合并平台线程等配置影响,横向对比时应保持配置一致。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0625
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00