# 内存优化
# 管理机制
# Android
内存分为系统和 V8 两块,两者都沿用了系统原有的内存管理机制
- V8 的内存回收机制可以参考 https://v8.dev/blog/trash-talk
- Android 系统内存管理机制可以参考 https://developer.android.com/topic/performance/memory-overview
# iOS
小游戏在 iPhone 上是沿用了 iOS 系统的内存管理机制
# 分析手段和工具
# 性能监控面板
在微信 Android 7.0.7 版本及以上,我们在小游戏开发版和体验版提供了性能监控面板,可以通过胶囊按钮打开,效果如下图所示
开发者可以监控不同内存的占用情况,通过不同内存的变化趋势来判断是否有内存泄漏的情况,各个指标含义如下
名称 | 含义 |
---|---|
summary.native-heap | native 内存 |
summary.system | 系统内存 |
summary.total-swap | 总 swap 内存 |
summary.graphics | 显存 |
summary.java-heap | java 内存 |
summary.total-pss | 总内存 |
summary.private-other | 其他私有内存 |
summary.code | 静态代码,资源内存 |
summary.stack | 栈内存 |
如果发现内存一直增长,为了排除是 GC 延迟的影响,可以在胶囊按钮中,点击开发调试中的 Request Force GC,会去立即调用一次 GC,以此对比内存的真实增长情况。
# Heap Snapshot
除此之外,微信 Android 7.0.7 版本及以上,我们在小游戏开发版和体验版提供了 Heap 内存快照的能力,同样是在胶囊按钮中打开,选择开发调试中的 Take Heap Snapshot,在界面弹出如下图所示的提示后,从提示中的位置把 heapsnapshot 拷贝到电脑上
之后在微信开发者工具中的调试器的 Memory 中,Load 拷贝出来的 heapsnapshot 文件,就可以查看 V8 的内存快照了,效果如下图所示
heapsnapshot 的使用方法可以参考
https://developers.google.com/web/tools/chrome-devtools/memory-problems/heap-snapshots
# V8-CPU-Profile
微信 Android 7.0.7 版本及以上,我们在小游戏开发版和体验版提供了 V8-cpu-profile 的能力,同样是在胶囊按钮中打开,选择开发调试中的 Start CPU Profile,界面上会弹出 “start cpu profiling..” 的提示
之后再在开发调试中选择 Stop CPU Profile,在界面弹出如下图所示的提示后,从提示中的位置把 cpuprofile 拷贝到电脑上
之后在微信开发者工具中的调试器单击右上角三个点的按钮 -> More tools -> JavaScript Profiler -> Load,加载刚才生成的 cpuprofile 文件,就可以查看 CPU 的使用情况了,效果如下图所示
左上角的下拉菜单可以选择如下三种模式:
- Chart:显示按时间顺序排列的火焰图。
- Heavy (Bottom Up):按照函数对性能的影响排列,同时可以检查函数的调用路径。
- Tree (Top Down):显示调用结构的总体状况,从调用堆栈的顶端开始。
这里我们选择 Tree (Top Down) 模式,按 Total Time 降序排列。可以看到有如下三列:
- Self Time:函数调用所耗费的时间,仅包含函数本身的声明,不包含任何子函数的执行时间。
- Total Time:函数调用所耗费的总时间,包含函数本身的声明及所有子函数执行时间。即:父函数的 Total Time = 父函数的 Self Time + 所有子函数的 Total Time。
- Function:函数名及路径,可展开查看子函数。
具体使用流程可以参考
https://developers.google.com/web/tools/chrome-devtools/rendering-tools/js-execution
# 优化建议
- 在 iOS 上,当微信客户端在一定时间间隔内(目前是 5 秒)连续收到两次及以上系统内存告警时,会主动进行小程序的销毁,并提示用户 「该小程序可能导致微信响应变慢被终止」。建议开发者注册
wx.onMemoryWarning
监听内存告警事件,并在在收到一次内存告警后,调用一次wx.triggerGC
清理内存,降低小程序被销毁的概率。 - 在场景切换的时候主动调用
wx.triggerGC
。 - 基础库 2.5.0 版本开始支持压缩纹理,其中 iOS 支持 pvr 格式,Android 支持 etc1 格式,压缩纹理可以有效降低图片资源占用内存大小,具体使用方式,可以参考引擎方提供的文档。
layabox https://ldc2.layabox.com/doc/?nav=zh-ts-4-14-7
egret https://docs.egret.com/engine/docs/render-2d/bitmapTexture/ktx
需要注意的是,etc1 需要纹理的尺寸是 2 的 n 次幂,同时 etc1 不支持透明图片,但可以通过 shader 等手段达到渲染透明 etc1 图片的目的