craftyjs / Crafty

JavaScript Game Engine
http://craftyjs.com
MIT License
3.41k stars 560 forks source link

Performance #952

Open Aliance opened 9 years ago

Aliance commented 9 years ago

Welcome.

I have the following question: why Crafty can not cope even with a light load, such as map of 36x36 tiles of 32 pixels each. If I use DOM - the browser crushes, if canvas - a little bit better. But if I add some more entities with animation - everything becomes very sad even in canvas.

For example, crafty competing analog, phaser, making it much faster.

mucaho commented 9 years ago

Interesting! Here are a couple of thoughts:

Aliance commented 9 years ago

I had Chrome 43 and somehow WebGL didn't work there, but chrome://flags said it was enabled. I updated Chrome to 44 version and It started to work. Magic? I have no time to see into the problem. Ok, now both crafty and phaser have WebGL support. But the situation is the same. (So before does, both had only native canvas).

As for events and entities, there were nothing special, I really think that it has to be okay. Later, I will prepare a fiddle for you to show my problem. Thanks.

FYI, I have not the slowest PC: 4x core, 8 GB RAM, Ubuntu OS.

mucaho commented 9 years ago

So I was curious about the performance of Canvas rendering in both engines and constructed a little demo in both engines.

There may be additional optimization options that I need to enable in Phaser (SpriteBatch is already included), because as of my testing on Firefox 39.0 on Win7, average FPS of demo in Phaser is 24 and average FPS of demo in Crafty is 56. This demo makes sure that the viewport is constantly moved like in a side-scrolling platformer. It would be great if we could optimize both demos even further and post more results from more people here.

Crafty code (similar results when using Sprite instead of Image)

<html>
  <head></head>
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crafty/0.6.3/crafty-min.js"></script>
    <script>
      Crafty.init(800, 600);
      Crafty.background('#2d2d2d');

      Crafty.load({images: ["https://rawgit.com/photonstorm/phaser-examples/master/examples/assets/sprites/mushroom2.png"]}, function() { // on success

          for (var i = 0; i < 100; i++)
            for (var j = 0; j < 100; j++)
                Crafty.e("2D, Canvas, Image")
                    .attr({x: i * 64, y: j * 64})
                    .image("https://rawgit.com/photonstorm/phaser-examples/master/examples/assets/sprites/mushroom2.png");

      }, function() {}, function() {});

      Crafty.bind("EnterFrame", function() {
        Crafty.viewport.x--;
        Crafty.viewport.y--;
      });
    </script>
  </body>
</html>

Phaser code (this variant with spriteBatch gives better results than game.add.sprite or game.add.image)

<html>
  <head></head>
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/2.4.2/phaser.min.js"></script>
    <script>
    var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });

    function preload() {
        game.load.image('mushroom', 'https://rawgit.com/photonstorm/phaser-examples/master/examples/assets/sprites/mushroom2.png');
    }

    function create() {
        game.stage.backgroundColor = '#2d2d2d';

        game.world.setBounds(0, 0, 100*64, 100*64);
        batch = game.add.spriteBatch();
        for (var i = 0; i < 100; i++)
            for (var j = 0; j < 100; j++)
                batch.create(i * 64, j * 64, 'mushroom');
    }

    function update() {
        game.camera.x++;
        game.camera.y++;
    }

    function render() {
    }
    </script>
  </body>
</html>
Aliance commented 9 years ago

Hello.

average FPS of demo in Phaser is 24 and average FPS of demo in Crafty is 56

How did you measured it?

mucaho commented 9 years ago

How did you measured it?

Firefox Menu Toolbar -> Tools -> Web Developer -> Performance (or Shift-F5) Click on the clock icon to start recording, click on it again after 10 secs to stop recording. You should see on the top a graphical display with the FPS measured.

I also updated the viewport / camera animation to be automatic in the example above to give more consistent results across runs.

Aliance commented 9 years ago

I'm using Chrome, but there is the same tool for capturing fps. But there no average fps, I can only calculate it by myself. Something like this:

On this screenshot I can not say anything about the average fps - sometimes it lower than 30fps, sometimes - 60 and more. The same for phaser. But I as for your demo - crafty is faster ;-)

mucaho commented 9 years ago

Yes, I tried to construct a similar example to your tilemap where you have performance issues. Are you using third party components for loading / displaying tile map?

Aliance commented 9 years ago

Hello. Sorry for being inactive for the last week. I construct an easy DOM test page, but the performance is not so good for me. And I don't even have collisions and sprite animations. If you try a Canvas test page - it will be okay.

Is it okay, that DOM with 36*36+1=1297 elements slows down page? In the first example, the only animation - is black movable item and parent div' top/left coordinates (viewport follow). May be change this to css animation?

200sc commented 9 years ago

The slowdown probably isn't just from the number of elements, but also from the fact that they are all simultaneously moving and none of them are being undrawn when they aren't on screen. Even so, having over a thousand DOM elements isn't a good idea. I don't use DOM at all in Crafty; it's far too slow. Canvas and WebGL exist to make things like tiled maps faster.

You can also get a FPS meter in chrome using it's javascript console (F12 or Ctrl+Shift+I): image