异名童鞋的微信小游戏性能优化

微信小游戏排行榜卡顿或无法滑动 微信小游戏为了保护其社交关系链数据,增加了子域的概念,子域又叫 开放数据域,是一个单独的游戏执行环境。子域中的资源、引擎、程序,都和主游戏完全隔离,开发者只有在子域中才能访问微信提供的 wx.getFriendCloudStorage() 和 wx.getGroupCloudStorage() 等API,用于实现一些例如排行榜的功能。 在我们制作子域过程中,会出现排行榜显示时,内存损耗会很高... 阅读详情

异名最近负责了一个微信小游戏的项目,在版本迭代间隙对游戏的性能调优进行了一次尝试。这个游戏是个打击类游戏,下面展示一下游戏的预览效果👇

性能指标

引擎和小游戏都有提供一个性能面板,给开发者们暴露了以下几个性能指标:

  • Frame time(ms)每一帧的时间。《RAIL模型》建议在 10 毫秒或更短的时间内制作动画中的每一帧。从技术上讲,每帧的最大预算为 16 毫秒(1000 毫秒/每秒 60 帧≈16 毫秒),但是浏览器需要大约 6 毫秒才能渲染每帧,因此建议每帧 10 毫秒或者更短。

  • Framerate(FPS)帧率,也叫每秒传输帧数(FPS:Frames Per Second),是指画面每秒传输帧数,通俗来讲就是指动画或视频的画面数;每秒钟帧数越多,所显示的动作就会越流畅,举个例子电影的帧频是 24,也就是说 1s 需要播放 24 张图片,但是实际上在游戏过程中一般人能接受的最低 FPS 约为 30Hz。帧率也非越高越好,因为显卡处理能力=分辨率×刷新率,分辨率不变的情况下,帧频越高,GPU 处理的数据量也会激增,引起卡顿。同理,分辨率也不是越高越好。在某些终端的性能面板下也会展示这三个相关的参数:rt-fps:实时帧率;ex-fps:极限帧率;min-fps:最小帧率;

  • Draw call 。CPU 和 GPU 是并行工作的,它们之间存在一个命令缓冲区。当 CPU 需要调用图形编程接口的时候,就会往命令缓冲区里面增加命令,当 GPU 完成上一次渲染命令的时候,就会继续从命令缓冲区中执行下一条命令,命令缓冲区里面的命令有很多种,而drawcall就是其中的一种。CPU 在提交drawcall的时候需要处理很多东西,比如一些数据、状态、命令等等。有些渲染卡顿问题就是因为 GPU 渲染速度比drawcall的提交速度快,可能上一次渲染完了,CPU 还在计算drawcall,所以drawcall的性能瓶颈在于 CPU。优化drawcall最有效的方法合批渲染,就是把大量小的drawcall合并成大的drawcall,减少drawcall的数量。

  • Tris 和 Verts 是渲染的三角面数以及顶点数,在 webgl 中只有三种基本图元,分别是点、线段和三角形,无论多么复杂的模型本质上都是由这三个基本图元绘制而来的,无论形状多么怪异,它们的本质都是由一个个顶点组成,GPU 将这些点用三角图元绘制成一个个的微小平面,再把这些三角网格互相连接,就能绘制出各种复杂的物体了;

    一般来说模型的顶点和三角形数越低,模型的复杂度就会越低,所以这两个参数在 3D 模型中比较有参考意义,设计师在输出 3D 模型的时候一般都会帮忙去合并一下网格。但是在大部分情况下,我们都会认为性能瓶颈在drawcall上,比如有两种情形,情景一是有 1000 个物体,每个物体的顶点数是 10,情景二是有 10 个物体,每个物体的顶点数是 1000,哪个情景的性能更好?首先我们要明白 GPU 的渲染速度是非常快的,渲染 10 个顶点组成的三角图元和 1000 个顶点组成的三角图元通常没啥区别,所以这两种情形中产生drawcall更少的情景二性能更好。当然如果你在shader里面对顶点做了一些特殊的处理,比如复杂的计算啥的,那就得权衡一下这两个指标的大小影响了

实操

降低DrawCall

想要减少 drawcall 就要从影响渲染状态的因素入手,比如纹理图片、纹理的渲染模式、Blend方式等等。但是在大部分项目中其实我们也不会有多大的需求去单独修改引擎的默认渲染参数,如果你改动了,那肯定是会打断合批的

一般情况下,在项目中降低drawcall收益比最大的其实是就是利用引擎提供的静态合图和动态合图的功能。静态合图就是自动图集了,或者使用第三方的图集工具TexturePacker,把资源中的散图进行合并,尽量让画面中的节点都使用一张图集,因为同一张图集的纹理状态都是一致的,所以能够达到渲染批次合并对纹理状态的要求;引擎中的动态合图有两种,一种作用对象是图片资源,是引擎默认启用的(但是小游戏中因为内存原因默认关闭),如果不希望使用就在资源面板中把Packable勾掉,或者把全局的合图开关关掉cc.dynamicAtlasManager.enabled = false; ;一种是针对label的,可以在label的cache模式中进行不同的模式切换。下面就介绍一下异名在这个项目中针对drawcall做的一些处理和以及收益:

合理管理节点

画面外的节点可以直接移除,drawcall从 50 降到了 23:

合理设置label的cache模式

把首页上三个label的cache模式改为bitmap,首页上的drawcall从 79 降低到 50。

有一些频繁更改的label,当cache模式改为char的时候,在我的苹果手机上差别不大,但是在小伙伴的安卓手机上流畅度上升十分明显

合并图集

在合并图集的时候需要根据画面的内容去做划分,尽量把同一个画面用的的图片资源打包成一个图集 。以游戏中的一个中后关卡为例(前面关卡的画面节点太少,差异不明显),drawcall均值从 190 降到了 90,drawcall峰值从 220 降到了 127。

通过Performance排查问题

在开发中的时候,异名会使用Chrome的DevTools,如果是在浏览器中排查性能问题需要屏蔽所有的浏览器插件,最好就是打开隐私模式来调试,因为插件在后台运行会造成干扰。但是在上线前异名会选择使用微信开发者工具的DevTools来再查看一下性能,因为在浏览器的中跑的项目是调试模式,一来没有做合图,而来它也没有经过小游戏的编译,所以为了减少和最终项目效果的偏差,最终会以微信开发者工具中的 Performance 指标为最终的参考指标。

和手机终端环境相比,我们的电脑的 CPU 是很快的,为了尽可能模拟用户的终端硬件情况,我们首先需要对 CPU 做一下节流,例如我现在选中的6x slowdown就会使我们本地 CPU 的运算速率比正常情况下降 6 倍。

这时候我们重新去生成录制结果,就可以发现面板上已经出现了醒目的红色告警信息了:

Recurring handler

聚焦放大然后把轴线定位到每个小的告警信息处,可以在Summary中看到浏览器给出的警告信息,我发现这里面的告警信息都是一样的,都是Recurring handler,而且有规律地出现,可以通过Initiator去查看重复出现的地方以及具体的执行代码:

虽然我们已经看到了代码执行的具体位置是requestAnimateFrame,但是这个 api 调用不是我们的业务逻辑,而是引擎的封装调用,引擎的帧回调应该是用requestAnimateFrame实现的,也就是说在update的钩子里面可能存在重复调用的逻辑,在这里就需要进一步地去分析了。

我们需要根据Main面板中火焰图也就是 JS 调用栈一步步去寻找并落实到具体的业务代码调用细节。如果能够定位到我们逻辑中的调用函数,马上对症下药就能解决了。

但是在异名的这个项目中Recurring handler给到的信息很难定位,task下面调用栈调用的都是引擎自身的渲染方法,当然横向去看调用的先后顺序的话,它在touchMove事件后面运行,这是一个排查方向,需要去分析自己的代码运行调用。

如果像异名遇到的这种情况,控制台只能定位到一堆引擎的渲染函数,而不能很明确地定位到我们的具体业务逻辑中,异名会建议放一放,因为重复渲染的问题可能会在long task拆分的过程中被 fix 掉。

Long task

可以通俗理解为一段执行时间很长的 js 逻辑就是长任务,"长任务"占用着主线程,即使我们的页面看上去准备好了,但是也不能响应用户的操作和点击等交互。至于这个执行时间多长才算是“长”呢?

《RAIL模型》建议我们每个任务最好都控制在 50 毫秒内,Chrome 在控制台中也给出了醒目的长任务提示:大型的脚本是长任务的主要原因,异名这里先举一个在项目中拆分长任务的简单的例子。异名的游戏中有个复活的逻辑,会在碰撞的回调中会处理一下血量和相关的掉血交互,然后当玩家血量耗尽就会唤起一个复活弹窗,这段逻辑就产生了一个long task,耗时 55.74ms,火焰图如下:

仔细分析一下,我的碰撞的逻辑处理和唤起复活弹窗虽然是顺序调用,但是它们之间算是一个比较清晰的逻辑界线,而且askResurgence这个函数是一个唤起 UI 弹窗的函数,既然产生了性能限制,我们就在这里做一个任务拆分:

// 用setTimeout包裹一下,把它放在下个宏任务执行
setTimeout(() => {
  this.askResurgence();
})

这时候我们再看拆分后的火焰图,long task标记已经消失了,本来一个长任务,被拆分成了 3 个任务(中间一个是 GC),而且三个任务的耗时相加和开始的长任务相比是折半了的。

异名通过排查梳理之后,发现一些连续的 UI 状态过渡都很容易造成长任务,异名的项目中还有好几处都是这种界线分明混合逻辑,当你遇到性能压力的时候或许可以像我一样做一下处理。

总结一下拆解大型脚本的时候,首先需要把大段的 js 逻辑重新梳理一遍,可以把一些能提前或者延后的状态,拆解到我们应用的空闲阶段去初始化或者变更,比如在首页就先把游戏过程中需要的数据加载进来,游戏过程的的逻辑中就不用再去加载这部分数据了。

但是这属于比较“宏观的”逻辑变更,大部分情况下我们的状态和逻辑变更都是很难提前或者延后的。我们还可以做一些时间颗粒度更小的逻辑拆分,那就是结合 js 的事件循环机制来处理我们的逻辑,像用Promise.then或者setTimeout去做一下任务延迟,甚至可以建立一个任务队列去做事件缓存等。

这篇《idle-until-urgent》有介绍到一些比较具体的拆解脚本措施。任务拆分是有风险的,无论是在应用的层面去提升或者延后逻辑,还是利用 js 的微任务或者宏任务去延后状态逻辑,都会有可能导致你的应用状态同步出现问题,所以在实操之后记得好好测试一下整个流程。

长任务还可以通过精简自身的逻辑来优化,像在一些循环中,如果可以做跳出判断自己是否有做;还有在一些地方你写的逻辑是否执行冗余或者无用,比如在异名的项目中这段交互逻辑👇

// 效果甚微的动画交互,干掉
this.node.setScale(1.2);
const frequency = getRandom(15, 40) / 100;
this.centerNode.runAction(
  cc.sequence(
    cc.scaleBy(frequency, 1.1),
    cc.scaleTo(frequency, 1)
  ).repeatForever()
);

它只是一个呼吸变化,在实际的画面效果中,这种小变化其实是很微弱的,可以认为它是一个可有可无的动画逻辑。那我们在做性能优化的时候,就需要果断地把它删除,这些冗余的逻辑干掉之后,game logic的数值就已经可以很明确地降低下来了。

其他

目前还存在较明显的性能方面:「发热、敌人数量增多时容易卡顿」

发热是个比较综合的问题,一般来说 CPU 导致发热,降低 CPU 的工作会有效减少发热。卡顿则受到帧频和 drawcall 的影响比较大,除了上面提到的,还有以下这些优化手段

  • 降低帧数:目前已动态设置帧频,游戏过程 60 帧,非游戏过程 30 帧

  • 减少帧回调:目前 update 中还有很大的逻辑优化空间

  • 减少内存使用:这块目前也有很大的优化空间,GC 回收,节点池,对象和节点复用、缓存等等,甚至包括一些贴图的引用释放等

  • drawcall 优化:其实还可以借助一些帧调试工具去进一步分析,项目的后期应该还会对drawcall优化进行再深入一点的探索

 

最后阐清几个指标的含义: 

 

1、ex-fps 不是平均帧率,是极限帧率,可以理解为在不受驱动帧率的限制下(大部分手机微 60fps),仅仅计算 js 运行耗时,可以达到的极限帧率。这个数字可以用于评估在满帧的前提下,运行性能是否有变化。 

 

2、game logic 的时间代表 update 中逻辑的耗时 

 

3、Renderer 的时间代表渲染的耗时 

 

4、Frame time = Game Logic + Renderer 

 

有一些优化的大原则,在此补充一下,即不要过早优化、最好的优化就是不用优化等等。优化是没什么万金油的,每个项目的性能瓶颈都不一样,需要根据项目的实际瓶颈,判断是该优化内存还是加载时间还是渲染时间等等。

 

以上就是异名在这两天针对性能优化做的一些尝试,后面项目迭代完成之后应该还会有一次针对性的优化尝试,到时候如果有别的收获再和大家分享。

 

因为异名这方面的经验比较缺乏,如果大家发现异名的实践方式有问题或者有遗漏的切入点,请帮忙指正。

 

如有侵权,请联系我。立刻删除。

微信小游戏 - 小游戏 vs H5 游戏性能对比和分析 这是个人关于微信小游戏系列文章的第三篇,在这系列文章里会描述 —— 如何把一些 Canvas/WebGL Demo 移植到小游戏环境并支持双端运行; 对小游戏在 Android 平台的运行时架构进行分析; 通过对移植的 Canvas/WebGL Demo 在小游戏和 Chrome for Android 浏览器上做 Benchmarking,对 H5 游戏 vs 小游戏的渲染性能进行对比和分析; 阅读详情

相关推荐

LinuxMint 22.1(Ubuntu24.04)下通过Wine完美运行同花顺远航版的实战指南

本文详细介绍了在LinuxMint 22.1(Ubuntu24.04)系统下通过Wine完美运行同花顺远航版的实战指南。从基础环境准备到深度优化,包括Wine环境配置、同花顺远航版安装、字体显示调优、任务栏兼容性修复等关键步骤,帮助Linux用户高效使用同花顺远航版进行股票交易和行情分析。

weixin_30919429的博客 570

微信小游戏帧同步demo(minigame-lockstep-demo)学习笔记

(这里不懂为什么逻辑帧比实际游戏帧下发周期小3,难道不会导致计算的时间preFrameTick大于实际时间nowFrameTick,然后帧堆在本地,全跑的后边快进的逻辑)

夜雨风亭 2661

解决uc浏览器劫持video标签问题

解决uc视频悬浮播放 ,video标签被浏览器劫持 ,vide0适配

smile_y_y的博客 3449

cocos creator 游戏源码_【社区精选】小游戏性能优化实战:DrawCall

本文原作者为陈皮皮,2020年7月2日发布于微信小游戏开放社区,原文《Cocos Creator 性能优化:DrawCall》前言在游戏开发中,DrawCall 作为一个非常重要的性能指标,直接影响游戏的整体性能表现。无论是 Cocos Creator、Unity、Unreal 还是其他游戏引擎,只要说到游戏性能优化,DrawCall 都是绝对少不了的一项。本文将会介绍什么是 DrawC...

weixin_39982452的博客 973

FPGA实现电机转速PID控制

通过纯RTL实现电机转速PID控制,包括电机编码器值读取,电机速度、正反转控制,PID算法,卡尔曼滤波,最终实现对电机速度进行控制,使其能够渐近设定的编码器目标值。

STATEABC的博客 7479

Ubuntu服务器通过IPV6端口转发搭建幻兽帕鲁私服实战

本文详细介绍了在Ubuntu服务器上通过IPV6端口转发搭建幻兽帕鲁私服的完整教程。针对只有公网IPV6地址的服务器环境,提供了从硬件检查、端口转发工具配置到游戏服务器安装的全流程解决方案,帮助玩家轻松实现多人联机游戏体验。

weixin_30652491的博客 490

游戏性能优化

异名最近负责了一个微信小游戏的项目,在版本迭代间隙对游戏的性能调优进行了一次尝试。这个游戏是个打击类游戏,下面展示一下游戏的预览效果????性能指标引擎和小游戏都有提供一个性能面板,给...

weixin_42257389的博客 4482

【100%通过率】2023华为od机试C卷【螺旋数组矩阵】C++ 实现

给出数字个数n和行数m(1 < n,m < 999),从左上角的1开始,按照顺时针螺旋向内写方式,依次写出2,3...n,最终形成个一m行矩阵。疫情期间,小明隔离在家,百无聊赖,在纸上写数字玩。输入一行,两个整数,空格隔开,依次表示n、m。4.数字不够时,使用单个*号占位。3.填充数字时优先填充外部。1:模拟整个过程打印即可。1.每行数字的个数一样多。小明对这个矩阵有些要求。2.列的数量尽可能少。

MISAYAONE的博客 1247

小游戏内存优化与性能优化 / DrawCall

二、性能优化 目前小游戏的性能瓶颈大多在JS层面,可以使用Chrome先去profiles性能热点,然后针对性地去做优化。 这里给出几点优化建议: 1、游戏中频繁更新的文字,推荐使用BMFont,系统字体会比较消耗性能。 2、优化Drawcall,尽可能减少Drawcall数量。 3、减少Mask组件的使用,该组件会导致游戏中的Drawcall数量变多。 4、禁用引擎的culling,禁用方法cc...

u013321328的专栏 1612

uniapp+renderJS+google map开发安卓版APP非小程序

uniapp+renderJS+google map开发安卓版APP非小程序,google map小叉号不显示,google map自定义marker右上角的小叉号如何去掉,uniapp+google map不显示

renkai721的专栏 667

第一章 电力电子仿真软件 PLECS简介

PLECS是瑞士Plexim公司开发的电力电子仿真软件,具有快速仿真、丰富元件库和热分析功能。软件提供单机版和嵌入MATLAB的版本,支持多平台安装且流程简单。首次运行需获取授权文件,提供60分钟演示模式。界面包含模型创建、帮助文档和元件库浏览器等功能区域,操作便捷。该软件是专业高效的电力电子系统仿真工具。

495

如何解决微信小游戏性能优化问题

深入剖析,全方位检测小游戏性能,优化体验触手可及。

UWA—简单优化,优化简单! 3851

CMake教程:C++ CMake自定义find_package并在其它项目使用

find_package 是 CMake 中一个非常重要的命令,用于在系统中找到外部库或包,并将其包含到项目中。: 要查找的包的名称。[version]: 可选的版本号。如果指定了版本号,CMake 会尝试找到该版本或更高版本的包。[REQUIRED]: 如果指定了这个关键字,找不到包时会产生一个错误并终止配置过程。: 指定要查找的包的组件。: 指定可选的组件,即使找不到这些组件,配置过程也会继续。: 指定查找包的模式,CONFIG表示查找配置文件,MODULE表示查找模块文件。

琅嬛福地 1563

微信小游戏的验收

微信小游戏验收需从技术指标、交付物完整性、安全合规性等多维度严格把关。核心技术指标包括加载速度(3-5秒)、帧率稳定(50-60帧)、内存控制(<500MB)及机型适配。交付物需包含完整源代码、美术原文件、技术文档及账号权限。业务逻辑要测试核心链路、断网重连及内购广告功能。安全验收重点检查防作弊机制、协议加密等。建议采用内部测试、第三方压测、灰度发布等流程,确保无重大bug后再支付尾款。特别警惕代码不规范或存在硬编码等问题,以免增加后期维护成本。

zhaoyin0335的博客 1022

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

微信小游戏制作坦克大战(五)敌方坦克可以发射炮弹

微信小游戏制作坦克大战(五)敌方坦克可以发射炮弹

lilihexiaoxiangege的博客 499

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

微信小游戏性能优化

微信小游戏性能优化是一个系统工程,需要从多个方面入手。通过合理的优化,可以显著提升游戏的流畅度和用户体验。

weixin_47467357的博客 1333

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

小游戏掉帧卡顿启动慢运行内存不足……这些问题有解吗?

https://www.fgba.net/sitemap.xml

wubaohu1314的博客 4004

creator性能指标

性能指标 引擎和小游戏都有提供一个性能面板,给开发者们暴露了下面几个性能指标: Frame time(ms)每一帧的时间。《RAIL模型》建议在10毫秒或更短的时间内制作动画中的每一帧。从技术上讲,每帧的最大预算为16毫秒(1000毫秒/每秒60帧≈16毫秒),但是浏览器需要大约6毫秒才能渲染每帧,因此建议每帧10毫秒或者更短。 Framerate(FPS)帧率,也叫每秒传输帧数(FPS:Frames Per Second),是指画面每秒传输帧数,通俗来讲就是指动画或视频的画面数;每秒钟帧数越多,所显示的动

weixin_43867973的博客 668

微信小程序截屏与录屏功能详解

微信小程序支持截屏和录屏功能,适用于教育、游戏、电商等场景。截屏通过wx.captureScreen实现,可自动保存课件等内容;录屏使用wx.startScreenRecording录制操作流程,如游戏通关过程。自定义绘制内容可通过wx.canvasToTempFilePath导出为图片。需注意用户授权、存储限制及系统差异。合理使用这些API能增强交互体验,满足多样化需求。

canglingyue的专栏 2063

【小程序】小游戏开发工具详解(下)

好久不见,本来计划周四就更新小游戏开发者工具学习的第二篇,无奈又来了个大需求,把人折腾得够呛。现在终于腾出时间输出一波了。话不多说,我们书接上回,继续学习!!!!!

伯子南的博客 4871

Unity Open Day 北京站-游戏专场:Unity 小游戏开发简介

【获取 2023 Unity Open Day 北京站演讲 PPT】赵亮:今天跟大家一起聊一聊使用Unity开发小游戏。小游戏是一种嵌在宿主应用内部,无需下载安装,可即点即玩的游戏产品形式。国内小游戏用户规模庞大,2018年,小游戏市场达到300亿元规模,在移动游戏市场也是一个不小的占比,大概占到20%左右,因此Unity正在逐步加大对移动端小游戏的支持。我的分享包括几个方面:首先,我们介绍一下当...

unityofficial的博客 986

用微信小游戏制作工具制作复刻飞机大战

复刻经典飞机大战,有简单版和升级版

I_1van的博客 525

游戏开发12课

unity 微信小游戏 性能优化

s178435865的专栏 4166

前端性能优化——性能监控

基础概念 网页出现白屏原因 网页从白屏到内容展示经历的过程 TTFB:Time To First Byte,首字节时间 FP:First Paint,首次绘制,绘制Body FCP:First Contentful Paint,首次有内容的绘制,第一个dom元素绘制完成 FMP:First Meaningful Paint,首次有意义的绘制 TTI:Time To Interactive,可交互时间,整个内容渲染完成 对应如下图: FP仅有一个div根节点 FCP包含页面的基本框架,但没有数据内容 FM

起风了 1466

统计页面的longtask(长任务)

【代码】统计页面的longtask(长任务)

weixin_43843897的博客 624

如何统计页面的long task(长任务)

定义:主线程执行时间超过 50ms 的任务(如 JavaScript 执行、样式计算、布局、绘制等)。影响:导致页面卡顿(Jank),尤其是动画或滚动时。检测标准:通过 Performance Observer API 监听 longtask 事件。

qq_40576344的博客 708
上一篇: Cocos Creator性能优化---DrawCall
下一篇: Mac进行一些操作时提醒Operation not permitted的完美解决
大头爱学习
博客等级 码龄7年 14粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值