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

1542183776360437.jpg

评论

6条评论
  1. Gravatar 头像

    刘宇 回复

    这个论坛是我看到介绍Animate CC和createjs最棒的。感谢你的分享,继续加油!

  2. Gravatar 头像

    小白 回复

    使用 createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED,createjs是调用requestanimframe,那应该不用再设置帧数了吧 createjs.Ticker.setFPS(60)。

    • Gravatar 头像

      ajex 回复

      @小白 createjs.Ticker.timingMode = createjs.Ticker.RAF可以不调用 详细看api

  3. Gravatar 头像

    sam 回复

    厉害

小白进行回复 取消回复

电子邮件地址不会被公开。