前言
性能稳定性是App的生命,Flutter带了很多创新与机遇,然而团队在享受Flutter带来的收益同时也迎接了很多新事物带来的挑战。
本文就内存优化过程中一些实践经验跟大家做一个分享。
Flutter 上线之后
闲鱼使用一套混合栈管理的方案将Flutter嵌入到现有的App中。在产品体验上我们取得了优于Native的体验。主要得益于Flutter的在跨平台渲染方面的优势,部分原因则是因为我们用Dart语言重新实现的页面抛弃了很多历史的包袱轻装上阵。
上线之后各方面技术指标,都达到甚至超出了部分预期。而我们最为担心的一些稳定性指标,比如crash也在稳定的范围之内。但是在一段时间后我们发现由于内存过高而被系统杀死的abort率数据有比较明显的异常。性能稳定性问题是非常关键的,于是我们火速开展了问题排查。
问题定位与排查
显然问题出在了过大的内存消耗上。内存消耗在App中构成比较复杂,如何在复杂的业务中去定位到罪魁祸首呢?稍加观察,我们确定Flutter问题相对比价明显。工欲善其事必先利其器,需要更好地定位内存的问题,善用已经的工具是非常有帮助的。好在我们在Native层和Dart层都有足够多的性能分析工具进行使用。
工具分析
这里简单介绍我们如何使用的工具去观察手机数据以便于分析问题。需要注意的是,本文的重点不是工具的使用方法介绍,所以只是简单列举部分使用到的常见工具。
Xcode Instruments
Instruments是iOS内存排查的利器,可以比较便捷地观察实时内存使用情况,自然不必多说。
Xcode MemGraph + VMMap
XCode 8之后推出的MEMGraph是Xcode的内存调试利器,可以看到实时的可视化的内存。更为方便的是,你可以将MemGraph导出,配合命令行工具更好的得到结构化的信息。
Dart Observatory
这是Dart语言官方的调试工具,里面也包含了类似于Xcode的Instruments的工具。在Debug模式下Dart VM启动以后会在特定的端口接受调试请求。可以参看官方文档。
观察结果
在整个过程中我进行了大量的观察,这里分享一部分典型的数据表现。
通过Xcode Instruments排查的话,我们观察到CG Raster Data这个数据有些高。这个Raster Data呢其实是图片光栅化的时候的内存消耗。
我们将App内存异常的场景的MemGraph导出来,对其执行VMMap指令得出的结果:
vmmap --summary Runner[40957].memgraph
vmmap Runner[40957].memgraph | grep 'IOKit'
我们主要关注resident和dirty的内存。发现IOKit占用了大量的内存。
结合Xcode Raster Data还有IOKit的大量内存消耗,我们开始怀疑问题是图内存泄漏导致的。经过进一步通过Dart Observatory观察Dart Image对象的内存情况。
观察结果显示,在内存较高的场景下在Dart层的确同时存在了较多Image(如图中270)的对象。现在基本可以确定内存问题跟Dart层的图片有很大的关系。
这个结果,我估计很多人都已经想到了,App有明显的内存问题很有可能就是跟多媒体资源有关系。通过工具得出的准确数据线索,我们得到一个大致的方向去深入研究。