内存优化

管理机制

Android

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

iOS

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

分析手段和工具

性能监控面板

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

monitoringpanel

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

名称含义
summary.native-heapnative 内存
summary.system系统内存
summary.total-swap总 swap 内存
summary.graphics显存
summary.java-heapjava 内存
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

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

  • 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 格式,压缩纹理可以有效降低图片资源占用内存大小,具体使用方式,可以参考引擎方提供的文档。Cocoshttps://docs.cocos.com/creator/manual/zh/asset-workflow/compress-texture.html

layaboxhttps://ldc2.layabox.com/doc/?nav=zh-ts-4-14-7

egrethttp://developer.egret.com/cn/github/egret-docs/Engine2D/bitmapTexture/ktx/index.html

需要注意的是,etc1 需要纹理的尺寸是 2 的 n 次幂,同时 etc1 不支持透明图片,但可以通过 shader 等手段达到渲染透明 etc1 图片的目的