1 qml或js内存方法的分析 ? ? ? qml和js的内存分析一般使用gammray或者qmlprofiler进行分析,但是目前这两个工具运行起来都有各自的局限性。?
1.1 qml和js持续的内存消耗 ? ? ? qml和js在Qt5中的内存管理是非常复杂的,且qml和js的原则是不关心内存的使用,并且qml和js本身是一个内存怪兽而且管理的方式和C++也是截然不同。 qml和js在创建和销毁component的方式与js的内存管理一致,都是通过gc进行管理,而Qt针对这块的内存也是lazy的方式进行gc,因为gc本身也有成本。所以qml和js在内存这块无法做到创建了一个页面,当页面销毁的时候就回收内存。 ? ? ?Qt内存在管理QObject QQuickItem这种对象的时候,都是通过父子管理进行管理,也就是当父亲对象销毁的时候,同时会销毁子对象,所以Qt的内存管理比较简单。但是这个策略本身也产生了一定的问题,因为只有父对象销毁的时候,子对象才会被销毁,在使用的过程中就会导致内存使用量偏高。 ? ? ? 在qml侧的ListView是最明显的一个场景, delegate会自动的创建ListView显示的条目,这些条目的父对象应该是ListView的 contentItem,所以就导致条目很难被回收内存, 所以在整个内存优化的时候需要重点考虑ListView的优化。? 1.2? qml和Js内存优化的方案 ? ? ? ?如下是经测试可以减少内存使用的方案。 (1)动态的创建和销毁组件,比如使用loader的方案; (2)通过trim的方法减少qmlengine的cache,减少程序的峰值; (3) 支持qtquickcompiler加速程序的启动速度和内存使用; (4) 减少QQuickView的使用,可以支持在App中支持多页面管理(也包括toast)。
1.3? qml和Js内存持续优化的建议 ?(1) ListView由于会多次的remove和add 条目,一些动画和操作也和listView的条目相关,所以建议尽量让delegate创建的条目简单,不要在条目中做复杂的东西,比如在条目中实现State相关的动画等等,尽量让条目简单; (2) 程序中的image可以尝试减少尺寸,这样会减少占用内存的大小; (3)可以在App中抽象一些组件,比如Text组件,所有的text公用一个font的配置,这样也会减少一些内存的使用; (4)减少js代码,尽量使用C++实现逻辑,通过c++管理可以精确的控制变量的声明周期; (5)更多的qml优化可以根据Qt官方的建议优化程序? ?https://doc.qt.io/qt-5/qtquick-performance.html。
2 qml和js优化方案描述 2.1 动态组件的创建和销毁 ? ? ? 有时程序的qml实现都是常驻内存的,也就是qml页面在程序启动之后就一直在内存中不会被销毁。这个策略优势是程序实现简单不容易出错,而且性能优异。 ? ? ? 还有一个方案是通过动态的创建和销毁页面来减少内存的使用。这里介绍通过loader的方式实现。?下面以taskmanager的 main.qml 为例子。
? ? ? 首先将可以动态创建和销毁的组件改为Component(taskManagerComponent ),如下图的root组件就可以改造为Component
?定义一个Loader组件taskManagerLoader,用于控制root component的创建和销毁。
根据程序的逻辑创建和销毁对象,通过loader的sourceComponent进行控制组件的创建和销毁:
?
?到这里就完成了一个最基础的动态创建和销毁的实现。 2.2 trim qml engine的cache ? ? ? ?Qml Engine会cache很多之前创建的component,即时有一些已经不在用的组件也会被cache住,所以为了减少内存的使用,可以在程序中找到一个合理的点去清理这些cache的组件减少内存使用。 下面是调用trim的方式来减少Qml Engine cache的组件。
2.3 使用qtquickcompiler ? ? ? qtquickcompiler在Qt5.12的开源版本中同样可以使用了,通过这个工具可以加速程序的启动和减少内存的使用,可能对qml和js的内存释放也有效果。而且可以免费使用。具体的使用方法可以查看Qt的官方文档,需要保证rootfs和toolchain的Qt版本完全一致。 ? ? ? ?使用qtquickcompiler的方法:https://doc.qt.io/archives/QtQuickCompiler/ ? ? ? 使用qtquickcompiler的优势和最新的compiler文档:? ? ? https://www.qt.io/blog/the-new-qtquick-compiler-technology 2.4 减少QQuickView的使用 ? ? ?有时启动了多个QQuickView用于显示不同的页面,在Qt里面每一个QQuickView可能有10m左右的内存占用,可以考虑在App中支持页面管理和迁移做成统一的模块,这样可以通过一个QQuickView完成所有的页面管理从而减少内存的使用。 ?
|