发布于 2016-05-28 23:21:25 | 213 次阅读 | 评论: 0 | 来源: 网友投递
HTML5超文本标记语言
万维网的核心语言、标准通用标记语言下的一个应用超文本标记语言(HTML)的第五重大修改。
HTML5作为新兴领域越来越热。然而在移动设备硬件性能弱于PC的背景下,对性能的需求显得更为重要,而HTML5性能优化前与优化后有着极大的差别,如何优化才能提高性能,对此熟知的人很少。本文以LayaAir引擎为例,通过代码示例详细阐述如何利用引擎对HTML5作出性能的极致优化。
主题包括:
代码执行基本原理
基准测试
内存优化
图形渲染性能
减少CPU使用量
其他优化策略
第1节:代码执行基本原理
LayaAir引擎支持AS3、TypeScript、JavaScript三种语言开发,然而无论是采用哪种开发语言,最终执行的都是JavaScript代码。所有看到的画面都是通过引擎绘制出来的,更新频率取决于开发者指定的FPS,例如指定帧频率为60FPS,则运行时每个帧的执行时间为六十分之一秒,所以帧速越高,视觉上感觉越流畅,60帧是满帧。
由于实际运行环境是在浏览器中,因此性能还取决于JavaScript解释器的效率,指定的FPS帧速在低性能解释器中可能不会达到,所以这部分不是开发者能够决定的,开发者能作的是尽可能通过优化,在低端设备或低性能浏览器中,提升FPS帧速。
LayaAir引擎在每帧都会重绘,在性能优化时,除了关注每帧执行逻辑代码带来的CPU消耗,还需要注意每帧调用绘图指令的数量以及GPU的纹理提交次数。
LayaAir引擎内置的性能统计工具可用于基准测试,实时检测当前性能。开发者可以使用laya.utils.Stat类,通过Stat.show() 显示统计面板。具体编写代码如下例所示:
Stat.show(0,0); //AS3的面板调用写法 Laya.Stat.show(0,0); //TS与JS的面板调用写法
Canvas渲染的统计信息:
关于滤镜、遮罩
尝试尽量减少使用滤镜效果。将滤镜(BlurFilter和GlowFilter)应用于显示对象时,运行时将在内存中创建两张位图。其中每个位图的大小与显示对象相同。将第一个位图创建为显示对象的栅格化版本,然后用于生成应用滤镜的另一个位图:
loadImage在加载完成的回调函数触发之后才可以正确获取宽高。
3.直接调用size设置:
Laya.loader.load("res/apes/monkey2.png", Handler.create(this, function() { var texture = Laya.loader.getRes("res/apes/monkey2.png"); var sp = new Sprite(); sp.graphics.drawTexture(texture, 0, 0); sp.size(texture.width, texture.height); Laya.stage.addChild(sp); }));
使用Graphics.drawTexture并不会自动设置容器的宽高,但是可以使用Texture的宽高赋予容器。毋庸置疑,这是最高效的方式。
注:getGraphicsBounds用于获取矢量绘图宽高。
根据活动状态改变帧频
帧频有三种模式,Stage.FRAME_SLOW维持FPS在30;Stage.FRAME_FAST维持FPS在60;Stage.FRAME_MOUSE则选择性维持FPS在30或60帧。
有时并不需要让游戏以60FPS的速率执行,因为30FPS已经能够满足多数情况下人类视觉的响应,但是鼠标交互时,30FPS可能会造成画面的不连贯,于是Stage.FRAME_MOUSE应运而生。
下例展示以Stage.FRAME_SLOW的帧率,在画布上移动鼠标,使圆球跟随鼠标移动:
Laya.init(Browser.width, Browser.height); Stat.show(); Laya.stage.frameRate = Stage.FRAME_SLOW; var sp = new Sprite(); sp.graphics.drawCircle(0, 0, 20, "#990000"); Laya.stage.addChild(sp); Laya.stage.on(Event.MOUSE_MOVE, this, function() { sp.pos(Laya.stage.mouseX, Laya.stage.mouseY); });
此时FPS显示30,并且在鼠标移动时,可以感觉到圆球位置的更新不连贯。设置Stage.frameRate为Stage.FRAME_MOUSE:
Laya.stage.frameRate = Stage.FRAME_MOUSE;
此时在鼠标移动后FPS会显示60,并且画面流畅度提升。在鼠标静止2秒不动后,FPS又会恢复到30帧。
使用callLater
callLater使代码块延迟至本帧渲染前执行。如果当前的操作频繁改变某对象的状态,此时可以考虑使用callLater,以减少重复计算。
考虑一个图形,对它设置任何改变外观的属性都将导致图形重绘:
var rotation = 0, scale = 1, position = 0; function setRotation(value) { this.rotation = value; update(); } function setScale(value) { this.scale = value; update(); } function setPosition(value) { this.position = value; update(); } function update() { console.log('rotation: ' + this.rotation + 'tscale: ' + this.scale + 'tposition: ' + position); }
调用以下代码更改状态:
setRotation(90); setScale(2); setPosition(30);
控制台的打印结果是
rotation: 90 scale: 1 position: 0
rotation: 90 scale: 2 position: 0
rotation: 90 scale: 2 position: 30
update被调用了三次,并且最后的结果是正确的,但是前面两次调用都是不需要的。
尝试将三处update改为:
Laya.timer.callLater(this, update);
此时,update只会调用一次,并且是我们想要的结果。
图片/图集加载
在完成图片/图集的加载之后,引擎就会开始处理图片资源。如果加载的是一张图集,会处理每张子图片。如果一次性处理大量的图片,这个过程可能会造成长时间的卡顿。
在游戏的资源加载中,可以将资源按照关卡、场景等分类加载。在同一时间处理的图片越少,当时的游戏响应速度也会更快。在资源使用完成后,也可以予以卸载,释放内存。
减少粒子使用数量,在移动平台Canvas模式下,尽量不用粒子;
2.在Canvas模式下,尽量减少旋转,缩放,alpha等属性的使用,这些属性会对性能产生消耗。(在WebGL模式可以使用);
3.不要在timeloop里面创建对象及复杂计算;
4.尽量减少对容器的autoSize的使用,减少getBounds()的使用,因为这些调用会产生较多计算;
5.尽量少用try catch的使用,被try catch的函数执行会变得非常慢;
文章出处:如何将HTML5性能发挥到极致