由于微信小游戏架构是基于C++渲染层来模拟Canvas渲染功能,因此在iOS端的性能一直不理想。 同样的程序版本与带有JIT加速的Android相差甚远。
微信小游戏提供的高性能模式,让iOS上的小游戏也具备JIT能力,通过切换到微信内部Webkit来运行游戏,大大提升了运行性能。
从微信小游戏官方文档中的水族箱测试中我们可以看到,在同一场景下,iPhone 11 Pro Max在高性能模式下达到了49 FPS,但普通模式下仅为13 FPS。
本文将从以下四个方面进行阐述:
由于内存问题在Android端表现良好,在iOS端反馈较多,因此本文仅介绍iOS端的内存优化。
高性能模式
高性能模式的介绍和使用请详细阅读微信小游戏开发文档:高性能模式(可以长按文末二维码)。
激活方式:登录微信公众平台->首页能力图模块->点击进入“生产改进包”->点击激活高性能模式。 激活成功后,通过将game.json中的iOSHighPerformance配置为true即可进入高性能模式。
去掉这个开关,就可以正常返回正常模式,以便对两种模式进行比较。
注意问题
在高性能模式下,游戏将会有更好的渲染性能和性能,但它对游戏的内存要求更加严格。
高性能模式下,小游戏运行在浏览器内核环境中,因此兼容性、内存消耗、稳定性等方面需要单独进行测试,普通模式下的测试结果无法复用。
在iOS设备中,iPhone 6s/7/8等2G RAM机型的内存限制为1G,iPhone 7P/8P/iPhoneX/XR/XSAMX/11等3G RAM机型的内存限制为1.4G。 一旦应用程序的内存使用量超过这个阈值,该进程就会被系统杀死。 因此,开发者必须保证峰值内存不超过这个值。
如果游戏没有针对内存进行优化,不建议开启高性能模式,否则在低端iOS机上很容易异常退出。 如果出现内存问题,可以参考本文的内存优化技巧,全面优化内存。
运行时内存结构
从上图可以看出,运行时内存由6部分组成。
JavaScript 堆
在高性能模式下,小游戏运行在浏览器内核环境中,因此JavaScript Heap包含了游戏逻辑代码内存。 通常我们可以将web-mobile端进行封装,利用Mac平台Safari浏览器的调试工具来远程调试手机safari的内存状态。 需要注意的是,JavaScript Heap 通常无法看到具体的物理内存使用情况。
WASM 资源
为了提高 JS 模块的执行性能,比如物理引擎计算,我们会直接将一些 C++ 代码编译成 WASM 代码片段,以达到优化的性能要求。 例如,Cocos Creator 引用的第三方物理库就是 WASM 版本。
基本库和画布
基础库可以理解为微信小游戏黑盒环境暴露的API封装,可以防止浏览器内核环境API暴露给开发者。 实际测试基础库内存占用约70M。 小游戏环境中创建的第一个Canvas是主Canvas,也是唯一一个可以将渲染面同步到主界面的Canvas,也就是呈现我们游戏的渲染性能。 Canvas 的内存占用与 Canvas 的宽度和高度成正比。
音频文件
音频文件内存是指加载到内存中的音频实例。
GPU资源
如顶点数据缓存、索引数据缓存、纹理缓存和渲染面缓存等。
诊断内存问题
下面介绍一些常用的iOS内存诊断工具,可以帮助我们快速定位内存问题并找到解决方案。
常用的iOS设备内存查看工具
注:iOS小游戏在不同模式下进程名称不同。
Xcode 仪器
XCode Instruments是XCode自带的应用程序运行时分析工具,同样适用于微信小游戏进程。
使用Activity Monitor,选择对应设备所有进程进行捕获创作人,等待进程列表刷新,输入webkit进行过滤,就可以看到所有进程的CPU和内存状态。
性能狗
Perfdog(Perfdog)是一款适用于iOS/Android/PC/主机平台的性能测试和分析工具。 具体使用方法可以参考:
选择对应的设置-进程名称即可查看相关性能数据。
可以参考【开发阶段的内存调优:从一开始就掌控一切| 微信开放文档】:。
微信开发者工具
微信开发者工具主要利用其调试器来跟踪内存数据。 操作流程如下:
进入调试开发者工具界面,勾选【内存】,然后刷新游戏,点击下图左上角的小圆圈按钮,开始录制。 录制完成后,会出现如下界面。
我们主要关注两个波形,一个是Main波形,用于查看逻辑帧调用栈,另一个是JS Heap的峰值曲线,用于观察内存增长的变化。 如果我们观察到某个时刻JS Heap值增加,那么我们可以查看逻辑帧调用栈来大致确认数据的来源。
通过以上步骤,我们就可以分析游戏的JS内存分配情况了。 那么当我们想要确定某块JS内存的来源和释放时,就需要用到下面的内存泄漏检测工具——实时内存诊断。
具体步骤如下:
点击左上角小圆圈按钮,进入下面的录音按钮。 直方图的出现表明某个内存块的创建,它的消失表明该内存块已被释放。 左上角的垃圾桶按钮是主动触发JS引擎GC的按钮。 点击它可以加快内存回收速度。
再次点击左上角的红色小圆圈按钮即可结束录制。 这时我们可以选择蓝色区域,然后内存块中包含的对象就会显示出来。 这些是内存中尚未释放的资源。 选择对象后,可以在Retainers界面看到该对象的内存引用关系。 此时就可以根据代码层的逻辑关系来推理是否应该释放内存对象,从而确认是否存在内存泄漏。
内存优化技巧
常见的微信小游戏项目的内存由以下部分组成:
小游戏基础库 引擎脚本内存 业务脚本内存 音频内存 字体内存 图像内存 画布内存
一旦我们知道了内存的组成部分,我们就可以针对不同的部分进行一些优化。
以iOS高性能模式为例,常用的内存优化技巧如下:
小游戏的基础库内存通常~=70M,属于常驻内存,无法优化。
引擎内存使用情况在加载时确定。 由于引擎加载会初始化渲染器,因此通常主Canvas内存使用情况也在此时确定。 可以通过配置多个渲染分辨率来优化内存使用。 在运行时,会根据引擎模块的需要动态添加一些缓存。 开发者可以根据功能需求,通过编辑器项目设置中的功能剪裁来减少引擎内存的使用。
脚本内存包含引擎和业务代码以及配置表数据。 根据游戏的开发量,业务代码和配置表数据内存将达到数百M大小游戏素材下载 免费,并且只能由用户进行优化。
单个双通道音频实例可能在20M左右。 播放音频后释放它会减少这种记忆损失。 它还可以简化为单通道音频以减少内存。
在国内,一般使用中文字体,加载后内存占用至少大于10M,所以尽量使用系统字体,并使用应用内的共享资源。 如果开发条件允许,可以使用Bitmap字体和SDF字体渲染。
图像内存是一种常用的资源。 根据加载需要网页游戏引擎下载,可以选择填充纹理然后释放,或者缓存在内存中以便下次重新填充纹理。 在iOS上,建议使用astc压缩纹理格式并禁用动态批处理,这样可以释放图像资源内存。 压缩纹理本身占用的内存也比png少50%以上,但是astc的文件大小会比png大,所以包大小会增大。 通常为了减小首包大小网页游戏引擎下载,尽量将图片资源放入小游戏分包或者远程分包中。
渲染 TTF 字体文本时将创建一个 Canvas 对象。 Canvas对象在使用后会被回收到缓存池中。 文本渲染的字体越大,缓存池就越大。 目前,该引擎不提供回收机制。 如果需要,可以修改引擎来释放Canvas。 缓存池。 如果游戏内存占用比较高,可以使用Bitmap字体来代替TTF字体。
还有其他的JS内存对象,比如JSON文件,根据引擎提供的能力按需释放。
本文由 Cocos 引擎官方技术支持团队提供,已同步至引擎官方开源仓库:微信小游戏内存优化指南(IOS)。 欢迎来到星叉。
参考文章
高性能模式| 微信开放文档
微信小游戏内存调优指南 - 知乎
性能测试实践| PerfDog助力微信小游戏/小程序性能调优 - 腾讯WeTest - 博客园
文章来源:https://docs.cocos.com/creator/manual/zh/editor/publish/ios/optimize.html