# 内存优化

# 管理机制

# Android

内存分为系统和 V8 两块,两者都沿用了系统原有的内存管理机制

# iOS

小游戏在 iPhone 上是沿用了 iOS 系统的内存管理机制

# 分析手段和工具

# 性能监控面板

在微信 Android 7.0.7 版本及以上,我们在小游戏开发版和体验版提供了性能监控面板,可以通过胶囊按钮打开,效果如下图所示

monitoringpanel

开发者可以监控不同内存的占用情况,通过不同内存的变化趋势来判断是否有内存泄漏的情况,各个指标含义如下

名称 含义
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 拷贝到电脑上

monitoringsave

之后在微信开发者工具中的调试器的 Memory 中,Load 拷贝出来的 heapsnapshot 文件,就可以查看 V8 的内存快照了,效果如下图所示

idememory

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..” 的提示

startcpuprofile

之后再在开发调试中选择 Stop CPU Profile,在界面弹出如下图所示的提示后,从提示中的位置把 cpuprofile 拷贝到电脑上

cpuprofilesave

之后在微信开发者工具中的调试器单击右上角三个点的按钮 -> More tools -> JavaScript Profiler -> Load,加载刚才生成的 cpuprofile 文件,就可以查看 CPU 的使用情况了,效果如下图所示

idecpuprofile

左上角的下拉菜单可以选择如下三种模式:

  1. Chart:显示按时间顺序排列的火焰图。
  2. Heavy (Bottom Up):按照函数对性能的影响排列,同时可以检查函数的调用路径。
  3. Tree (Top Down):显示调用结构的总体状况,从调用堆栈的顶端开始。

这里我们选择 Tree (Top Down) 模式,按 Total Time 降序排列。可以看到有如下三列:

  1. Self Time:函数调用所耗费的时间,仅包含函数本身的声明,不包含任何子函数的执行时间。
  2. Total Time:函数调用所耗费的总时间,包含函数本身的声明及所有子函数执行时间。即:父函数的 Total Time = 父函数的 Self Time + 所有子函数的 Total Time。
  3. Function:函数名及路径,可展开查看子函数。

具体使用流程可以参考

https://developers.google.com/web/tools/chrome-devtools/rendering-tools/js-execution

# 优化建议

  1. 在 iOS 上,当微信客户端在一定时间间隔内(目前是 5 秒)连续收到两次及以上系统内存告警时,会主动进行小程序的销毁,并提示用户 「该小程序可能导致微信响应变慢被终止」。建议开发者注册 wx.onMemoryWarning 监听内存告警事件,并在在收到一次内存告警后,调用一次 wx.triggerGC 清理内存,降低小程序被销毁的概率。
  2. 在场景切换的时候主动调用 wx.triggerGC
  3. 基础库 2.5.0 版本开始支持压缩纹理,其中 iOS 支持 pvr 格式,Android 支持 etc1 格式,压缩纹理可以有效降低图片资源占用内存大小,具体使用方式,可以参考引擎方提供的文档。

Cocos https://docs.cocos.com/creator/manual/zh/asset/compress-texture.html?h=%E5%8E%8B%E7%BC%A9%E7%BA%B9%E7%90%86

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 图片的目的