Egret社区

白鹭引擎的性能优化技巧

2016-3-25 15:20
1649535
本题已加入常见问题汇总 » 性能优化最佳实践,更多性能优化最佳实践相关的话题欢迎关注讨论


引子

最近有不少开发者发了一个 Demo 给我,想了解为什么不同的 HTML5 游戏引擎之间的性能差异这么大,特别是白鹭引擎性能并不是很好。
对此我很惊讶,仔细研究了一下这个 Demo。
经过研究发现,制作这个Demo的开发者使用引擎的方法有些小纰漏,可能是对白鹭引擎不太了解的原因。
今天做这个示例,是为了给大家解惑答疑,并引导一下白鹭引擎的正确用法。


示例一: 帧动画


测试设备:iPhone6P + 微信

从这个示例中可以看出,白鹭引擎的帧动画性能似乎很差。但是经过我的优化,帧频从34帧提升至了56帧。
为什么有如此差距呢?原来是开发者提供的Demo 采用了错误的动画制作方式。
白鹭引擎官方提供了 MovieClip API 来进行帧动画创作,
而评测的开发者错误的使用了Container 在每帧切换 Bitmap 的方式实现帧序列动画。错误代码截图如下:

在这种情况下,由于每帧都要进行 addChild / removeChild 操作,这样的话每帧都会进行显示列表修改,派发事件等操作,这样自然性能很低。
而这种问题的正确处理方式应该采用以下代码:

[JavaScript] 纯文本查看 复制代码
var texture = this.mArrayTextures[index];
bitmap.texture = texture;
index++;


采用这样的方式,每一帧只需要更改一下 texture 的引用,无需对显示列表进行修改,性能可以得到很大的提升。



示例二:显示对象旋转位移

测试设备:小米4 + 微信 ( X5 Blink内核 )
从这个示例中可以看出,白鹭引擎的显示对象旋转位移的性能和其他引擎的差不多。但我观察白鹭引擎的 Profiler 面板,感觉还可以有性能提升,所以我修改了一下测试用例,进一步提升了白鹭引擎Demo的性能,从14帧提升至了19帧。
这个性能提升的方法是关闭白鹭引擎的脏矩形特性。
熟悉白鹭引擎的开发者可能了解,白鹭引擎采用独立研发的脏矩形技术,只会渲染屏幕上发生改变的部分。而世面上大部分其他引擎都是无论画面内容是否改变,都会进行强制全部重绘。
为了能获取画面上的显示对象是否“脏”了,必然会付出额外的性能开销。但是通常在正常的游戏场景中,这种开销是值得的,因为一个游戏场景在多数情况下,都不是所有显示对象全部都在移动的,而是静止与动态的相结合。举个例子:
在没有脏矩形的情况下,由于所有显示对象都需要渲染,游戏的帧频只有16。
但是在开启脏矩形功能之后,游戏里只有14%的内容需要被重绘,性能就大幅提升到了 54 帧。
这表明,作为一个游戏引擎,白鹭引擎针对游戏常用的场景进行了更有针对性的优化。
当然,也会有开发者表示,我们的游戏就是所有显示对象都在不停的动,那这种情况下性能反而不好怎么办呢?其实白鹭引擎提供了一个 API 来去处理这种极端情况
[JavaScript] 纯文本查看 复制代码
this.stage.dirtyRegionPolicy = "off";

关闭脏矩形之后,由于不需要再进行脏区域,所以帧频从14提升到了19。关于这一点的详细介绍,官方文档传送门:http://edn.egret.com/cn/docs/page/719
或者在白鹭引擎开发者社区 http://edn.egret.com/cn 中搜索“脏矩形”,搜索结果第一篇文章就是。




示例3:5000个显示对象缩放位移
在这种场景下,传统的Canvas渲染方式几乎失去了意义,分别只有5帧和10帧。当然,和上个Demo一样,关闭脏矩形之后,白鹭引擎的性能也得到了提升。
但是很多开发者都了解,在这种情况下 WebGL 模式可以获得更好的性能。白鹭引擎在 2.5 版本因为引入了脏矩形这样的重大架构调整,几乎所有代码都被重写,(相信去年9月份升级版本的开发者会对此也有所吐槽),所以在新版本中,我们暂时关闭了 WebGL 渲染模式,但是在我们的开发版本中,WebGL的性能也得到了很大的提升。我们会尽可能努力让 WebGL 这个特性重新回到白鹭大家庭中。



示例四:90个骨骼动画
在测试场景中,开发者评测的白鹭引擎的Demo存在两个问题:
首先是骨骼动画创建非常缓慢,这其实是评测代码中的一个疏忽带来的逻辑错误:

在创建骨骼动画的时候,正确的做法应该是第一次进行创建,之后的创建采用之前创建的缓存就可以了,就像上图中的代码一样的思路。
但是上图中的代码有一个小疏忽,就是用了 this.i 就行了判断,而 this.i在整个创建过程中,都是0,所以每次创建骨骼动画,都没有使用之前的缓存,自然创建速度非常缓慢。
正确的代码应该是 if ( i == 0 )而不是 if ( this.i == 0 ),开发者(特别是之前做过 Flash 的开发者,比如我)一定要注意在 JavaScript 中,this.i 和 i 是完全不一样的。这种错误通常埋得非常深,查起来也是非常苦逼。
其次,白鹭引擎的这个Demo 帧频很低,只有15左右,而其他引擎达到了38帧。经过我们的评测,这是由于两方面导致的:
一是白鹭引擎和骨骼动画 DragonBones 的适配层存在优化空间,我们修改了这个适配层( 在 GitHub DragonBonesPerformance 分支上 )。
二是作为一个强大的骨骼动画库,DragonBones 包含了很多强大的功能,但是针对简单的骨骼动画,这些功能反而带来了一些副作用。我们为了解决这个问题,在 Egret 2.0 版本开始引入 FastArmature 模式进行优化,但是优化的仍然不够彻底,接下来我们会继续努力完善这一部分。
在经过初步的优化之后,白鹭引擎的骨骼动画 Demo 性能已经提升至了 32 帧,敬请期待白鹭引擎的下个版本。



结论
开发者放出的 4个 Demo 采用白鹭引擎的最佳实践进行优化后,性能均得到了大幅提升。
强调一下,本次所有测试(除了 WebGL)都采用白鹭引擎的 3.0.5 版本的标准公开 API 进行测试,未进行任何的特殊处理。



我们的问题
白鹭引擎也不是完美的。在仔细对比性能测试中,我们也发现了白鹭引擎的一些问题,如:
  • 引擎内部存在一个小疏漏,重复赋值了 imageSmoothing 属性。修改后在特定情况下性能提升了10%。
  • DragonBones 和白鹭引擎的适配层代码逻辑可以优化,优化后帧频从 20提升至了32。
  • WebGL 模式需要加快速度重新提供给开发者
  • 白鹭引擎缺乏一份完善的性能优化指导性建议。我们会尽快提供一份官方的性能优化最佳实践,以帮助开发者以正确的“姿势”做出更精彩的游戏。
以上问题会在白鹭引擎双周更新的版本中逐步提供给开发者。



尾声
现在目前主流市场的几个引擎,无论从功能,性能,工具和易用性上,大家都有了飞速发展。
欢迎大家PK技术和良性沟通,一起努力提高。
白鹭引擎在2016年的上半年主要主要的工作方向是进一步完善和优化2D渲染,资源管理,网络优化等相关能力,除此之外进一步加强3D方面的能力。
最近有不少用白鹭引擎的新技术制作大型游戏的线上案例,
例如多人在线ARPG《暗黑之王》
实时在线回合RPG《主宰之王》等等


在最后的最后,感谢各位开发者对白鹭一如既往的支持 ^ ^


参与人数 4威望 +5 银子 +16 贡献 +3 收起 理由
小书呆子 + 1 + 1 + 1 赞一个!
unsilence + 3 + 5 + 1 分析透彻,可圈可点,真诚贴切.
Once + 1 + 5 + 1 赞一个!
东北大客 + 5 赞一个!

查看全部评分

分享到 :
13 人收藏

35 个回复

倒序浏览
xsstomy  斑竹 | 2016-3-25 16:12:46
前排占位!
yjtx  官方团队 | 2016-3-25 16:21:46
占座~~~~
dily3825002  社区管理员 | 2016-3-25 16:23:57
看到this.i震惊了~~~
Once  斑竹 | 2016-3-25 16:25:43
强势围观
Joeky  官方团队 | 2016-3-25 16:41:04
sxtaosdo  自成一派 | 2016-3-25 16:41:09
必须支持啊!!!!!!
Mr-Harbor  略有小成 | 2016-3-25 16:42:21
标记一下
unsilence  官方团队 | 2016-3-25 16:43:16
给力!!!!!
cfcf  初窥堂奥 | 2016-3-25 17:19:13
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号

Powered by Discuz! X3.2 © 2001-2019 Comsenz Inc.

返回顶部