Flutter 性能优化 Tips(2)

本文探讨了在Flutter应用中进行内存优化的方法,包括图片和对象管理、内存泄漏预防以及使用Observatory工具监控性能。通过测量帧率、CPU使用和内存占用,以及如何使用Observatory分析函数调用和内存分配,提供了实用的优化策略和案例分析。
摘要由CSDN通过智能技术生成
  • 把耗时的计算放到独立的isolate去执行
  • 检查不必要的 saveLayer
  • 检查静态图片是否添加缓存
  • relayout boundary:参考
  • repaint boundary:参考

内存优化

在内存优化方面,我们的目标是希望减少应用内存占用,减少被系统杀死的概率,同时尽可能的避免内存泄露,减少内存碎片化。

内存优化策略

  • 加载对象过大?如图片质量和尺寸不做限制就加载
  • 加载对象过多?如加载长列表;在调用频率很高的方法中创建对象
  • 合理设置缓存大小/长度
  • 在内存不足时或离开页面时清空缓存数据
  • 使用ListView.build()来复用子控件
  • 自定义绘图中避免在onDraw中做创建对象操作,或者相同的参数设置
  • 复用系统提供的资源,比如字符串、图片、动画、样式、颜色、简单布局,在应用中直接引用
  • 内存泄露的问题?比如dispose需要销毁的listener等
  • 不可见的视图是否也在build?
  • 页面离开后的网络请求是否取消?

如何获取内存状态

Dart 提供了一个性能检测工具Observatory,我在最后一部分会进行详细介绍

优化证明

优化证明的意义

性能优化不像其它的开发需求只要完成功能即可,它需要通过统计和数据来证明优化的效果。比如帧率有了多少提高?CPU占用率降低了多少?内存占用减少了多少?对比其它优化策略,哪个优化效果好?

优化证明的流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

举个例子

以检查流畅性为例

1. 在profile模式下运行并开启Performance Overlay,整体测试app
2. 找到帧率报红色的模块
3. 把页面孤立出来,并多次测量,并得到baseline(参照)帧率数据。比如长列表页面出现了卡顿,我们可以用TestDriver写一个ListView滑动的性能测试(更多参考Flutter gallery)

scroll_pref.dart

void main() {
enableFlutterDriverExtension();
runApp(const GalleryApp(testMode: true));
}

scroll_perf_test.dart

void main() {
group(‘scrolling performance test’, () {
FlutterDriver driver;

setUpAll(() async {
driver = await FlutterDriver.connect();
});

tearDownAll(() async {
if (driver != null)
driver.close();
});

test(‘measure’, () async {
final Timeline timeline = await driver.traceAction(() async {
await driver.tap(find.text(‘Material’));

final SerializableFinder demoList = find.byValueKey(‘GalleryDemoList’);

for (int i = 0; i < 5; i++) {
await driver.scroll(demoList, 0.0, -300.0, const Duration(milliseconds: 300));
await Future.delayed(const Duration(milliseconds: 500));
}

// Scroll up
for (int i = 0; i < 5; i++) {
await driver.scroll(demoList, 0.0, 300.0, const Duration(milliseconds: 300));
await Future.delayed(const Duration(milliseconds: 500));
}
});

TimelineSummary.summarize(timeline)
…writeSummaryToFile(‘home_scroll_perf’, pretty: true)
…writeTimelineToFile(‘home_scroll_perf’, pretty: true);
});
});
}

在命令行下执行以下命令

flutter driver --target=test_driver/scroll_perf.dart

这个命令会:

  • build 目标 app,并把它安装到设备上
  • 运行位于test_driver/目录下的scroll_perf_test.dart的测试( flutter drive 能帮你找到带 _test后缀的同名文件)

Test Driver 将会安装 app 到设备上,再跳转到 Material-GalleryDemoList 页面,做5次滑动列表的操作。执行完成后会借助 TimelineSummary ,在build目录下生成两个json文件:home_scroll_perf.timeline.jsonhome_scroll_perf.timeline_summary.json。这里我们看一下timeline_summary.json文件的内容

{
“average_frame_build_time_millis”: 5.6319655172413805, # 平均每帧 build 时间
“90th_percentile_frame_build_time_millis”: 10.216,
“99th_percentile_frame_build_time_millis”: 17.168,
“worst_frame_build_time_millis”: 20.415, # 最长帧 build 时间
“missed_frame_build_budget_count”: 21, # build 期丢帧数
“average_frame_rasterizer_time_millis”: 14.234294964028772, # 平均每帧光栅化时间
“90th_percentile_frame_rasterizer_time_millis”: 22.338,
“99th_percentile_frame_rasterizer_time_millis”: 42.661,
“worst_frame_rasterizer_time_millis”: 43.161,
“missed_frame_rasterizer_budget_count”: 112,
“frame_count”: 116,
“frame_build_times”: [

],# 所有帧的 build 时间
“frame_rasterizer_times”: [

] # 所有帧的光栅化时间
}

4. 优化
5. 用步骤3的方法再次测量,对比baseline得出确切的优化效果

Flutter 提供的性能调试 API

更多可以参考官方文档

性能检测利器 Observatory

Observatory 是用于分析和调试Dart应用程序的工具。Observatory允许您根据需要查看正在运行的Dart虚拟机(VM),并提供实时,即时的数据报告。您可以使用它来浏览应用程序的很多状态。

打开Observatory

有2种方式:

  1. 在 androidStudio 中打开Flutter Inspector面板,点击小闹钟图标,如下图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 再命令行中运行flutter run,应用启动成功后,命令行中会输出一个 url,把 url copy 到浏览器即可。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

打开Observatory面板,要先选择isolate,表示当前应用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

主要页面

下面是性能优化常关注的几个页面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1. CPU Profile

app的时间都花在哪了?

进入这个页面后要一般需加载个几秒钟,so be patient。图表的下部按cpu占用比例做了一个列表,反映的是函数的调用次数和执行时间(划重点)。一般排在前面的函数(这些函数是?有待学习)都不是我们写的dart代码。如果你发现自己的某个函数调用占比反常,那么可能存在问题。

注:flutter程序的cpu profile和官方文档上的数据展示不太一样,没有VM tags,所以对于百分比的具体含义有待研究。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

采样过程:它每隔一定时间对isolate做采样,采样的数据存储在一个环形缓冲区(叫做profile),它能存放约2分钟的数据,一旦缓冲区满了,它会用最新的sample替换掉最旧的。

  • Profile contains:采样时长和对应的采样数
  • Sampling:采样频率,默认1000Hz,即每毫秒采样一次
2. Allocation Profile

内存都被谁吃了?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Heap 堆,动态分配的Dart对象所在的内存空间

  • New generation: 新创建的对象,一般来说对象比较小,生命周期短,如local 变量。在这里GC活动频繁
  • Old generation:从GC中存活下来的New generation将会提拔到老生代Old generation,它比新生代空间大,更适合大的对象和生命周期长的对象

通过这个面板你能看到新生代/老生代的内存大小和占比;每个类型所占用的内存大小。

为了debug的方便,我们可以获取到某段时间的内存分配情况:点击Reset Accumulator按钮,把数据清零,执行一下要测试的程序,点击刷新。

为了检查内存泄露,我们可以点击GC按钮,手动执行GC。

Accumulator Size:自点击Reset Accumulator以来,累加对象占用内存大小 Accumulator Instances:自点击Reset Accumulator以来,累加实例个数 Current Size:当前对象占用内存大小 Current Instances:当前对象数量

3. Heap Map

是否出现内存碎片化

heap map 面板能查看old generation中的内存状态

它以颜色显示内存块。 每个内存页面(page of memory)为256 KB,每页由水平黑线分隔。 像素的颜色表示对象的类ID - 例如,蓝色表示字符串,绿色表示双精度表。 可用空间为白色,指令(代码)为紫色。 如果启动垃圾收集(使用“分配配置文件”屏幕中的GC按钮),堆映射中将显示更多空白区域(可用空间)。 将光标悬停在上面时,顶部的状态栏显示有关光标下像素所代表的对象的信息。 显示的信息包括该对象的类型,大小和地址。 当你看到白色区域中有很多分散的其它颜色,说明存在内存碎片化,可能是内存泄露导致的。

其它

1. Code Coverage

知道哪些代码执行了,哪些没有执行

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 绿色:已执行的代码
  • 红色:未执行的代码
  • 没有颜色:不可执行的代码

应用场景:写某个类的单元测试,跑完测试后,可以查看哪些代码没有覆盖到,进而补全

2. Class/Instance 信息

查看某个实例的状态,比如我们的项目中使用了Flutter_redux,页面的展示来源与状态树,当页面出现了非预期的效果,我们可以通过Observatory查看状态树

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

举个例子

Observatory 帮我找到循环调用的真凶
总结

性能优化涉及了应用的方法面面,很难一言以蔽之。本文我们主要讨论了性能优化的两大主题 —— 流畅性和内存优化,并分别介绍了他们的检测方法和优化策略。另外,我们在优化的同时也要加强优化的证明,用数据说话。最后,我强烈推荐大家尝试一下 Observatory 这个工具,开发中如果遇到了奇怪的问题,没准它能帮你找到答案。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

学习分享

①「Android面试真题解析大全」PDF完整高清版+②「Android面试知识体系」学习思维导图压缩包

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

DF完整高清版+②「Android面试知识体系」学习思维导图压缩包**

[外链图片转存中…(img-z9hSCSmX-1712262368210)]

[外链图片转存中…(img-spEQEqMc-1712262368210)]

[外链图片转存中…(img-VVe1cT61-1712262368211)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值