原文连接:Performance testing of Flutter apps 做者:Filip Hracek (from Flutter team)android
Flutter 在默认状态下就能运行得很是快,这点很是棒! 可是否这就意味着你彻底不须要考虑性能呢?git
答案是否认的,编写一个速度很是慢的 Flutter 应用是彻底可能的。然而,另外一方面你也能够充分利用这个框架,让你的 app 不只快速,高效,并且使用更少的 CPU 时间和电量。github
这就是咱们想要的!在一个有意义的指标上来比较两个版本的应用在统计上明显的差别web
在 Flutter 中有一些性能优化的通用指导原则:chrome
你可能很难相信,对于大多数性能优化的问题来讲,它们的答案通通指向了这句话——“它究竟取决于什么?”。对于特定 Widget 是否值得进行特定优化,并付出维护成本?在特定状况下的特殊处理是否合理?shell
对于这些问题惟一有用答案是测试和测量。量化每一个选择对性能的影响,并根据该数据作出决定。浏览器
好消息是 Flutter 提供了出色的性能分析工具,例如包含 Flutter Inspector 的 Dart DevTools(目前还处于预览版),或是 Android Studio 中的 Flutter Inspector(安装了 Flutter 插件下)。你可使用 Flutter Driver 操做应用,并在 Profile 模式下保存性能信息。性能优化
然而坏消息是,如今的手机实在是太过智能了。😂bash
系统级守护进程须要根据当前负载调整 CPU 和 GPU 单元的速度,可是 iOS 和 Android 的管理器却很难量化 Flutter 应用的性能。总的来讲这仍是一件好事,由于它确保了平稳的性能,同时也消耗尽量少的电量。网络
然而缺点是你彻底能够经过提升其效率以显著加快应用的运行速度。
下面的例子中,你能够看到如何在应用中循环打印一些无心义的 print 语句,使得管理器切换到更高的档位,从而让应用运行更快速,性能更加可预测。
管理器的问题:在默认状况下,你没法相信这些数字。在上面这个盒子图中,咱们在 x 轴上进行单独运行(用它们开始的确切时间标记),并在 y 轴上表示构建时间。正如你所看到那样,当咱们引入一些彻底没必要要的打印语句时,它居然会缩短(而不是增长) build 时间。
在这个实验中(上图),更差的代码反而致使了更快的构建时间,更快的光栅化时间和更高的帧率。若是客观上更差的代码会获得更好的性能,那么你就不能遵循这些指标。
上面仅仅是为了解释为什么移动应用性能基准不直观,以及测试困难的一个例子。
接下来,我将分享一些 Google I/O app 上 Flutter 的例子,Developer Quest。
正如咱们刚才所说的,现代操做系统根据负载和一些其余的启发式调整每一个 CPU 和 GPU 的频率。(例如,触摸屏幕一般会让 Android 手机将其优先级置于更高的档位。)
在 Android 上你可以直接关掉这些管理器,咱们称之为“scale locking”。
#!/usr/bin/env bash
GOV="userspace"
echo "Setting CPU governor to: ${GOV}"
adb shell "echo ${GOV} > /sys/devices/system/cpu/cpu${CPU_NO}/cpufreq/scaling_governor"
ACTUAL_GOV=`adb shell "cat /sys/devices/system/cpu/cpu${CPU_NO}/cpufreq/scaling_governor"`
echo "- result: ${ACTUAL_GOV}"
复制代码
Flutter Driver 可以自动执行应用。你能够阅读 flutter.dev 上性能分析的文章,了解如何使用它来分析应用。
startSync()
方法 和 finishSync()
方法,来添加自定义时间轴事件。例如,当你想要测试特定方法的性能时,这颇有用。将 startSync()
放在它的开头,并在方法结束时使用 finishSync()
。for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
复制代码
时间轴是你运行 profile 模式下输出的原始资料。Flutter 将此信息转储到可被 chrome://tracing
加载的 JSON 文件中。
chrome://tracing
,而后点击“Load”,选择那个 JSON 文件。你能够在这篇 简短指导 中得到关于它的更多信息。(一样有 Flutter Timeline tooling,但目前还处于 tech preview 阶段。由于在 Flutter 的 timeline tooling 准备就绪以前,Developer Quest 项目就已经开始了,因此我还没用过那个。)chrome://tracing
的 timeline 中移动,以及使用 1234 来更改操做模式。/path/to/your/android/sdk/platform-tools/systrace/systrace.py --atrace-categories=gfx,input,view,webview,wm,am,sm,audio,video,camera,hal,app,res,dalvik,rs,bionic,power,pm,ss,database,network,adb,pdx,sched,irq,freq,idle,disk,load,workq,memreclaim,regulators,binder_driver,binder_lock
开启 Android systrace。 而后经过 flutter run test_driver/perf.dart --profile --trace-systrace
运行 app。最后,经过 flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/
启动 Flutter Driver(其中 NNNNN 是 Flutter run
上运行的端口给你的)。最好能看尽量多的指标,但我发现一些相比其余更有用的指标。
build 的时间 和 光栅化的时间 仅在真正严格的性能测试中才有用(默认状况下提供的度量标准是 TimelineSummary
),这些测试除了 UI 以外不会包含太多其余内容。
不要把 TimelineSummary.frameCount
看做计算每秒帧数(FPS)的方法。Flutter 的配置文件工具不能给你提供真实的帧速率信息。TimelineSummary
虽然提供了 countFrames()
方法,但它只会计算已完成的帧构建了多少次。一个优化良好的应用能够限制没必要要的重建,每秒的帧数比常常重建的未经优化的应用程序少不少。
我我的得到的最有用的数据是经过测量运行 Dart 代码所花费的总 CPU 时间获得的。这会算上 build 方法和外部执行的代码。假设你在 scale-locked 的设备上运行配置文件测试,总 CPU 时间能够很好地估算你的应用程序将消耗更多仍是更少的电。
MessageLoop:FlushTasks
事件的范围。在制做 Developer Quest
的时候,我编写了一个 Dart 工具来提取它们。当这些都设置好了以后,你就可以自信地比较提交和实验。下面,你能够看到一个很常见困境的答案:“这种优化值得维护开销吗?”
我认为对于这个状况来讲,答案是确定的。只需几行代码,咱们应用的每一个自动测试平都可以减小 12% 的 CPU 时间。
然而,本文的主要内容是,不一样的测量方式可能会反映处很是不一样的东西。尝试过于宽泛地推断性能测量也许十分符合直觉,但倒是错误的。
换句话说:“它究竟取决于什么”。咱们应该信奉这句话。
以上即是翻译的所有内容,我认为这篇文章对咱们构建高效的 Flutter 应用具备很大的指导意义,因此便翻译出来分享给你们。
如如有译误还请指出。