createjs性能实测与性能优化实测
刚接触一门新语言的童鞋都会想,这个语言性能怎么样?市面上HTML5的引擎那么多,肯定也有童鞋好奇createjs的性能相比别的引擎差别有多少。
好今天我们就做几个demo试一下,我们在同屏渲染2000个动画,看看帧频会有多少,优化后又会有多少。
随着电脑性能的逐渐提升,2000个对象已经看不出效果了,最近我把demo的对象提升到了4000个,截图没有换,截图无视。
我们先新建了2000个movieclip,不做任何优化看看帧频有多少。
http://www.ajexoop.com/demo/xiaolv/index1.html
大家可以看到只有22帧左右,不行,movieclip效率很差。
那我们换成sprite能有多少呢,来试试。
http://www.ajexoop.com/demo/xiaolv/index2.html
大家可以看到,已经有32了,比刚才movieclip好多了,由此得出结论,要求效率比较高的项目尽量用sprite而不是用movieclip。
虽然比movieclip好,但是实际效率还是不太好,那我们试着优化一下。
demo2中我的sprite代码是这样的。
var cls = {}; (function() { function People(){ this.Container_constructor(); this.spriteData = { images: ["sprite.png"], frames: {width:80, height:80, regX: 40, regY:40}, animations: { play:[0,3,"play",0.2] } }; this.spriteSheet =new createjs.SpriteSheet(this.spriteData); this.sprite = new createjs.Sprite(this.spriteSheet,"play"); this.addChild(this.sprite); } var p = createjs.extend(People,createjs.Container); cls.People = createjs.promote(People, "Container"); }());
也就是说上面的代码一个sprite一个spriteSheet,那我们试试分开来,我们这样写
//main.js var canvas,stage,spriteData,spriteSheet,images={}; canvas = document.getElementById("mainView"); function init() { stage = new createjs.Stage(canvas); var loader = new createjs.LoadQueue(true); loader.addEventListener("fileload", handleFileLoad); loader.addEventListener("progress",progressHandler); loader.addEventListener("complete", completeHandler); loader.loadManifest([{src:"sprite.png", id:"sp"}]); createjs.Ticker.setFPS(60); createjs.Ticker.addEventListener("tick", stageBreakHandler); } function handleFileLoad(evt) { if (evt.item.type == "image") { images[evt.item.id] = evt.result; } } function progressHandler(event) { } function completeHandler(event) { event.currentTarget.removeEventListener("fileload",handleFileLoad); event.currentTarget.removeEventListener("progress",progressHandler); event.currentTarget.removeEventListener("complete",completeHandler); spriteData = { images: [images.sp], frames: {width:80, height:80, regX: 40, regY:40}, animations: { play:[0,3,"play",0.2] } }; spriteSheet = new createjs.SpriteSheet(spriteData); for(var i = 0;i < 2000;i++) { var people = new cls.People(); stage.addChild(people); people.x = Math.random()*900; people.y = Math.random()*500; } FPS.startFPS(stage); } function stageBreakHandler(event) { stage.update(); } var cls = {}; (function() { function People(){ this.Container_constructor(); this.sprite = new createjs.Sprite(spriteSheet,"play"); this.addChild(this.sprite); } var p = createjs.extend(People,createjs.Container); cls.People = createjs.promote(People, "Container"); }());
我们把spriteSheet拿了出来,因为动画都是一样的,一个数据就可以了,然后测试一下。
http://www.ajexoop.com/demo/xiaolv/index3.html
可以看到提升了一点点,不是很多,说明createjs内部对于图片是有处理的,如果是一张图片,用的是一个数据,不过这样还是节省了类的大小,多少提升了一点效率,蚊子肉也是肉,如果图片源一样的话,还是用一个spriteSheet。
上面的代码,我们都是放在了container的容器里,如果我们减少容器的嵌套会怎么样呢,再来试一把。
//main.js var canvas,stage,images={}; canvas = document.getElementById("mainView"); function init() { stage = new createjs.Stage(canvas); var loader = new createjs.LoadQueue(true); loader.addEventListener("fileload", handleFileLoad); loader.addEventListener("progress",progressHandler); loader.addEventListener("complete", completeHandler); loader.loadManifest([{src:"sprite.png", id:"sp"}]); createjs.Ticker.setFPS(60); createjs.Ticker.addEventListener("tick", stageBreakHandler); } function handleFileLoad(evt) { if (evt.item.type == "image") { images[evt.item.id] = evt.result; } } function progressHandler(event) { } function completeHandler(event) { event.currentTarget.removeEventListener("fileload",handleFileLoad); event.currentTarget.removeEventListener("progress",progressHandler); event.currentTarget.removeEventListener("complete",completeHandler); var spriteData = { images: [images.sp], frames: {width:80, height:80, regX: 40, regY:40}, animations: { play:[0,3,"play",0.2] } }; var spriteSheet = new createjs.SpriteSheet(spriteData); for(var i = 0;i < 2000;i++) { var sprite = new createjs.Sprite(spriteSheet,"play"); stage.addChild(sprite); sprite.x = Math.random()*900; sprite.y = Math.random()*500; } FPS.startFPS(stage); } function stageBreakHandler(event) { stage.update(); }
http://www.ajexoop.com/demo/xiaolv/index4.html
看一下demo已经有42左右了,可以满足一般的游戏了,这说明createjs减少容器的嵌套,对提升性能效果很大。
虽然刚才的demo最大已经有42的帧频,而且一般游戏也不需要同屏2000个对象,但是很多HTML5的其他引擎的demo都能同屏渲染上万个,createjs可以么?答案是可以的,但是就要用到webgl。官网的下载地址里下载完以后会有个webgl-0.8.1.min.js这个文件,我们把这个文件引用进去,当然代码也需要变动,需要用到SpriteStage。
(createjs1.0之后的版本不使用SpriteStage了,直接使用stageGL,相关性能测试可以移步:https://www.ajexoop.com/wordpress/?p=809)
var stage,spriteData,spriteSheet,images={} function init() { stage = new createjs.SpriteStage("mainView", false, false); stage.updateViewport(1920, 950); var loader = new createjs.LoadQueue(true); loader.addEventListener("fileload", handleFileLoad); loader.addEventListener("progress",progressHandler); loader.addEventListener("complete", completeHandler); loader.loadManifest([{src:"sprite.png", id:"sp"}]); createjs.Ticker.timingMode = createjs.Ticker.RAF; // createjs.Ticker.setFPS(60);//raf模式自动设置成60帧 所以不需要设置帧频 createjs.Ticker.addEventListener("tick", handleTick); } function handleTick(event) { stage.update(); } function handleFileLoad(evt) { if (evt.item.type == "image") { images[evt.item.id] = evt.result; } } function progressHandler(event) { } function completeHandler(event) { event.currentTarget.removeEventListener("fileload",handleFileLoad); event.currentTarget.removeEventListener("progress",progressHandler); event.currentTarget.removeEventListener("complete",completeHandler); spriteData = { images: [images.sp], frames: {width:80, height:80, regX: 40, regY:40}, animations: { play:[0,3,"play",0.2] } }; spriteSheet = new createjs.SpriteSheet(spriteData); for(var i = 0;i < 15000;i++) { var sprite = new createjs.Sprite(spriteSheet,"play"); stage.addChild(sprite); sprite.x = Math.random()*1920; sprite.y = Math.random()*950; } FPS.startFPS2(stage); }
我们可以看到,其实代码也没差多少,只不过用SpriteStage,很多createjs的其他显示类的api就不能用了。
其中 createjs.Ticker.timingMode = createjs.Ticker.RAF;(具体机制可以搜索requestAnimationFrame,createjs的底层就是使用这个的)
这回既然用了webgl我也疯狂一回,把数量加到了15000,再来看看效果如何。
http://www.ajexoop.com/demo/xiaolv/index5.html
夸张吧,但是效率能达到60+,说明语言不分好坏,用得好性能都能上去,createjs也不例外,不过webgl不是所有浏览器都支持,这点所有HTML5引擎都一样。
之前所有的demo的性能展现都是根据我这台机器来的(中等机器),不同性能的机子,帧频的展现也会不一样。
最后来总结一下吧,平时大家在写createjs的时候,很多童鞋,特别是flash转createjs的程序员,经常会用很多的movieclip,而且是一层嵌一层,这会造成程序卡顿,特别是移动端,不要为了图方便,就随意的用animateCC做动画(用animateCC也是有方法的),如果你是一个程序员应该想到提升自己而不是方便就行,当然动画师不强求。至于webgl这东西,从我现在的经验来讲,浏览器能支持的不用也不会卡,不支持的怎么样都卡,所以也不强求。优化的方法还有很多,希望大家能一起分享,谢谢。
demo下载链接:http://pan.baidu.com/s/1gfqgK3x
刘宇
这个论坛是我看到介绍Animate CC和createjs最棒的。感谢你的分享,继续加油!
小白
使用 createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED,createjs是调用requestanimframe,那应该不用再设置帧数了吧 createjs.Ticker.setFPS(60)。
ajex
@小白 要的哦 😀
匿名
@小白 😐 😀
ajex
@小白 createjs.Ticker.timingMode = createjs.Ticker.RAF可以不调用 详细看api
sam
厉害