iOS 14 egret 游戏卡顿问题分析和部分解决办法
现象
总体而言,iOS 14 渲染性能变差,可以从以下三个测试看出。
测试1:
简单demo,使用egret引擎显示3000个图(都是同一个100*100 png 纹理),逐帧做旋转。(博客园视频播放可能有问题,视频地址:https://github.com/kenkozheng/kenkozheng.github.com/blob/master/WebGL/ios14/video/1.mp4?raw=true)
视频中,黑色机器是iOS14.0,白色是iOS13.7,都是iphone 7plus。
虽然从视频中来看,iOS 14的fps还要高一些,但实际上14明显卡顿。原因是:Egret检测的fps是web层面通过requestAnimationFrame得到的,实际上和画面渲染没有严格对等关系。
改为通过perfDog,从native层面看帧频,看到iOS14只有13fps,而旧版本有40+,这也解释了为什么肉眼看起来14的渲染要更卡顿。
测试2:
复杂demo,使用egret引擎显示candy爆炸龙骨动画100个。(博客园视频播放可能有问题,视频地址:https://github.com/kenkozheng/kenkozheng.github.com/blob/master/WebGL/ios14/video/2.mp4?raw=true)
和上边测试1类似,egret左上角的fps显示并不准确,通过perfDog检测,实际帧频只有7fps左右。
测试3:
在复杂demo基础上(还是100个爆炸动画),修改egret代码,禁用颜色混合shader,所有元素渲染都统一使用普通shader。
由于龙骨设定为24fps,而实际fps有40,从视频中肉眼无法看出卡顿。所以这里视频省去。
也是类似的情况,iOS14比iOS13渲染fps低,iOS14只有8fps左右,而iOS13有40+fps。
测试4:
使用自研的简单webgl引擎(min2d),显示15000个100*100的png。(博客园视频播放可能有问题,视频地址:https://github.com/kenkozheng/kenkozheng.github.com/blob/master/WebGL/ios14/video/3.mp4?raw=true)
情况和egret引擎类似,还是iOS14明显卡顿,虽然界面显示fps较大,但实际帧率只有10fps左右。题外话:自研引擎性能略比egret好10%左右,但上边测试中能支持15000个图片,只是因为自研引擎没有做像素密度加倍尺寸渲染。
由此可见,iOS14 webgl性能确实比iOS13有明显下降。
分析
从egret的监控来看,js层面的耗时(包括顶点计算、调用webgl)都没有明显问题,iOS14比iOS13甚至还有一些优化。但实际渲染帧频,iOS14又明显比iOS13更低,问题应该出于safari内部对webgl接口的具体实现上有一些改变。
调试过程中,发现两个比较奇怪的现象:
1、本来满帧运行,但运行一段时间后,会下降到40-50fps。
2、50个爆炸动画播放时能稳定在50fps,但增加到60个爆炸动画之后,fps会断崖式下跌,到14fps左右。
从这个现象,推测内部实现在显存管理上,可能出了较大变化,可能有一些缓存,数据达到阈值后,可能有反复的数据交换。
首先,排查了几个方面:
1、drawCall推送vertex buffer的方式(webgl.bufferData vs webgl.bufferSubData)
egret每次drawCall使用webgl.bufferData推送顶点数据,这个方法每次推送覆盖整个bufferData;而webgl.bufferSubData可以指定offset,只覆盖部分数据。
但由于每次修改的数据量并不多,两者从理论和实际测试来看,都没有区别。
2、推送纹理、webgl初始化设定(抗锯齿等)、frameBuffer
上述方面,egret的设置都属于通用做法,并没有特殊,而且调整了参数后,性能并没有提升。
3、去除shader的alpha计算
也没有明显变化
4、去除blendMode处理
虽然有明显的性能提升,但在iOS14上的性能提升并不比iOS13上的提升更大,blendMode并不是iOS14变慢的主要因素。
而且BlendMode是游戏素材制作的必需选项,影响到透明叠加效果,无法简单去除。
上述几个方面都没有找到解决方式。
另外,另外的游戏引擎cocos creator,官方提出在cocos引擎中使用了多次drawCall共享vertex buffer和index buffer的优化技术(也是常规的优化手段),但在iOS14中反而变成了性能瓶颈,已针对做了处理(针对iOS14,每次drawCall使用不同的vertex buffer)。
参考:
https://forum.cocos.org/t/ios-14-web/97808
https://github.com/cocos-creator/engine/pull/7415/files#
分析egret的实现,设置了默认每次drawcall最多同时批处理2048个元素,对于一般sprite来说,一个元素就等于一个图,等于一个长方形,等于两个三角形,也等于六个顶点。
进一步,egret在初始化时,会创建一个12288个unsigned short组成的index buffer,然后bindBuffer到GPU。这个过程一般只执行一次,后续不会再绑定,也不会再创建新的buffer(网格拉伸情况除外,会换一个indexbuffer数据内容)。
那么,每次drawcall时,无论是多少个元素,哪怕只有1个元素(6个顶点)都会使用这个12288长度的index buffer。
从这个角度来看,确实可能存在优化的可能。
引擎改进
从现象和分析过程得出,iOS14确实有性能下降,我们可以从一些维度,尽可能挽回一些性能下降。
目前确认可以从引擎层面改进的是index buffer问题。
改进的策略是:判断是否iOS14,如果是,就在每个drawcall前,推送新的index buffer和vertex buffer数据,这些数据只包括本次渲染所需,没有多余数据。
具体改动:
WebGLRenderContext的$drawWebGL方法中,判断是否Mesh绘制,在非Mesh绘制情况下,切分vao中的indices array和vertices array,取出本次drawcall所需部分,上传给gpu。而且,在这个情况下,drawData要忽略offset,改为固定的0(offset是对应vertex buffer中包含多次drawcall数据时才使用,现在每次按需推送,所以就不需要offset了)。
同样渲染50个爆炸龙骨动画,修改后的版本性能有明显提升。 如下图,左侧1分钟是原有版本下绘制50个爆炸龙骨动画的fps情况,右侧是优化后版本的fps情况。原有版本平均10fps,而优化后平均20fps(这个帧率可能和前边测试demo略有差异,是由于iphone渲染一段时间后变慢有关)。
index buffer的使用调整,确实能解决上述爆炸龙骨动画在iOS14的性能问题。
另外,排查过程中,还发现一些值得探索的方向:
1、带filter和不带filter的图元,如何批处理。egret引擎原来没有做批处理。如果能实现这个优化,将极大减少龙骨的渲染drawCall。
2、调整像素密度绘制策略。egret引擎默认以屏幕像素密度作为倍数绘制webgl画布,但游戏素材并没有这么大,这个扩大渲染对性能有影响,但视觉效果没有提升。
第2点,尤其可以针对低端机型,例如系统版本在6.x或以下的android,这部分机型本来性能就较差,但还可能按2-3倍像素去绘制webgl,渲染帧率就更低。
例如,oppo r9 系统版本5.1,屏幕像素密度3,强制以密度1绘制,性能能够提升30%。
除上述提到的方向外,针对iOS14,可能还存在更多针对性优化的方向,但还需要针对具体的场景,逐个分析。
性能结论
iOS14对比iOS13和以前版本,在webgl渲染性能上有明显下降,尤其在drawcall次数较大、渲染面积较大或使用较多颜色混合滤镜情况下,下降尤其明显。
针对iOS14,虽然能在一些方面改善性能,但单纯从js角度,无法让webgl渲染性能恢复到iOS13的水平,只能寄望于苹果官方自行修复底层问题(已有不少反馈到苹果论坛)。
素材开发建议
除了从引擎底层解决iOS14卡顿问题,另外,针对游戏业务素材,还可以做一些改动,提高渲染性能:
1、减少龙骨动画层级,减少图元个数;
2、避免使用颜色混合和BlendMode(混合模式);
3、避免使用有大面积透明区域的图片,可以把图片切分为只有有效内容的多个小图。
另外,iOS14在js层面监控到的帧频不是真正的webgl渲染帧频,性能优化需要直接连接perfDog做监控。
iOS 14 egret 游戏卡顿问题分析和部分解决办法的更多相关文章
- H5:加载原理,慢加载和卡顿原因分析,
前端H5工作原理: 请求和显示原理 H5页面卡顿原因分析: 1.动画太多:渲染重绘占用GPU 2.页面操作导致重绘频繁 3.页面元素复杂:资源类标签太多(图像/视频/dom树太长) 4.内置webvi ...
- 基于webstorm卡顿问题的2种解决方法
基于webstorm卡顿问题的2种解决方法:https://www.jb51.net/article/128441.htm
- android studio 一直卡在Gradle:Build Running的解决办法
转:android studio 一直卡在Gradle:Build Running的解决办法 在使用AS开发安卓应用程序的时候经常会遇到Gradle build running一直在运行甚至卡死的 ...
- ios iphone ipad上iframe的宽度会扩大的解决办法
这个问题,我从网上查了下,好像是属于ios的bug,android,windows都没有问题. 解决办法,就是在iframe加载完成后,设置 iframe里面body的宽度为多少PX. $(" ...
- Android中app卡顿原因分析示例
在知乎回答了一个“为什么微博的app在iPhone比Android上流畅”的问题.后面部分是一个典型的动画卡顿的性能分析过程,因此帖在这里.有编程问题可以在这里交流.知乎链接. =========== ...
- ios添加-webkit-overflow-scrolling依然卡顿
项目由vue-cli2创建 在overflow: auto区域内滑动ios手机出现卡顿,搜索资料后添加-webkit-overflow-scrolling: touch ios bug: 1.滑动区域 ...
- 【bug清除】Surface Pro系列使用Drawboard PDF出现手写偏移、卡顿、延迟现象的解决方式
最近自己新买的New Surface Pro在使用Drawboard PDF时,出现了性能问题,即笔迹延迟偏移,卡顿的问题. 排查驱动问题之后,确认解决方案如下: 将Surface的电池调到性能模式, ...
- DEDE织梦 后台特别卡,有时响应超时的解决办法
跟大家一样,大致情况是: 1.打开后台首页第一次没问题,但是刷新或者点其他菜单就一直卡着了. 2.关掉浏览器重新进首页没问题,但是一旦进了首页再打开php页面就卡死了. 3.服务器返回Maximum ...
- ios 页面过长卡顿的情况
解决方案如下: -webkit-overflow-scrolling: touch;
随机推荐
- 记一次select2赋值动态数组的坑
var roles = $td.eq(3).text().split(","); var arr = []; //循环去除每个值前后的空格,否则下拉框赋值回显出错for(var i ...
- HTTP 的前世今生,那些不为人知的秘密
每个时代,都不会亏待会学习的人. 大家好,我是 yes. HTTP 协议在当今的互联网可谓是随处可见,一直默默的在背后支持着网络世界的运行,对于我们程序员来说 HTTP 更是熟悉不过. 平日里我们都说 ...
- SolrJ使用
1 //向solr索引库中添加索引 2 public void addDoc() throws Exception { 3 //创建solr客户端的对象 4 HttpSolrClient client ...
- Python-语法糖(装饰器)
什么是高阶函数? -- 把函数名当做参数传给另外一个函数,在另外一个函数中通过参数调用执行 #!/usr/bin/python3 __author__ = 'beimenchuixue' __blog ...
- Python练习题 006:输出九九乘法表
[Python练习题 006] 输出九九乘法表 --------------------------------------------------- 照理这题不难,逻辑关系弄对了就好办,但数学渣的我 ...
- Java知识系统回顾整理01基础01第一个程序03Eclipse下载安装
Eclipse是最流行的java 集成开发环境IDE(Integrated Development Environment) 下载安装Eclipse两种方式 一.方式1:Eclipse官网下载安装 链 ...
- Matlab中加汉明窗 ahmming 作用
转自:http://www.cnblogs.com/lxy2017/p/4049124.html 1.什么是汉明窗? 语音信号一般在10ms到30ms之间,我们可以把它看成是平稳的.为了处理语音信号, ...
- C/C++的二分查找
假设有一种温度传感器,已经测得它的电压和温度的对应关系,将电压值以ADC转换后的数字量的值表示,形成温度-AD值的对照表,如下. 大致成一条反比关系的曲线. ADC的底层驱动已经写好,对外有一个接口可 ...
- 二进制搭建kubernetes-1.18.6单master集群
master组件 kube-apiserver kubernetes API集群的同一入口,各组件协调者,以RESTful API提供接口服务,所有对象资源的增删改查和监听操作都交给APIserver ...
- MySQL基础 :基本知识点大纲