mariannoga

What is wrong with Phaser3 performance?

Recommended Posts

I have been playing around with phaser3 and electron. I have developed simple 2D tile based map and the code just runs a single scene at the moment. It doesn't even render anything beyond a single frame - my update function inside the Scene get called multiple times a second but exits immediately if there is no update needed. However I can see in Dev Tools' Performance tab that rendering routines get called quite often. It results in unwanted CPU usage and my laptop fan goes through the roof and wakes up my neighbours. It's kinda annoying and I hope somebody can give me an idea about how to improve it. Platform is 2015 Macbook Pro 13''.

I am using "phaser": "3.10.1", "electron": "^1.8.7"

Ask any questions. I have attached a screenshot below that might give you some clue:735277712_ScreenShot2018-06-27at22_59_57.thumb.png.14b7a949dfeffb0153c98b6e04977ba1.png

Share this post


Link to post
Share on other sites

This isn't enough information to even begin to help I'm afraid. There's no indication of canvas size, texture size, map size, etc. Bailing out of an update loop early won't make any difference. What's actually in the Scene?

Share this post


Link to post
Share on other sites

Thought you might say more information is needed. I wasn't really sure what is relevant so let me answer your questions.

Size is set as follows when opening Electron window: 

mainWindow = new BrowserWindow({ width: 1200, height: 768, resizable: false });

Then the phaser config takes it as follows:

// main game configuration
const gameConfig: GameConfig = {
	width: window.innerWidth,
	height: window.innerHeight,
	type: Phaser.AUTO,
	parent: 'game',
	scene: MapScene,
	fps: {
		target: 2
	}
};

The map size is (80 tiles x 16 pixels) x (50 tiles x 16 pixels) and that is pretty much what is in the scene. Tiles are PNG images with transparent background so there can be up to 3 sprites in some tiles one on top of another.

Please let me know if you need more information.

Share this post


Link to post
Share on other sites

Assuming you want to render just 2 frames instead of as much as the system can handle, try changing the fps part of the config into:

fps: {
  target: 2,
  min: 2,
  forceSetTimeOut: true
}

Unless you force usage of setTimeout, Phaser will use RAF to trigger updates and render, which will try to sync to your display refresh rate.
Also without that `min` part, the ticker would lower the delta time to 5 FPS (the default), so if you want 2, set the min too.

Share this post


Link to post
Share on other sites

Thanks for the response. I set the target, min and forceSetTimeOut as instructed.

Render seems to be firing every 20ms which would be 50Hz. this simply means it did not work as expected. no change to the CPU usage. thanks for the efforts but I think I will need to try something else. Any other ideas?

 

Screen Shot 2018-06-29 at 22.03.25.png

Share this post


Link to post
Share on other sites

Seriously? 

7 hours ago, Antriel said:

Hmm, looking at the source, it seems the ticker doesn't honor the fps settings and just goes with 16 ms ticks with `forceSetTimeOut`.

 Not sure if that's intended or a bug @rich?

Well, that clarifies one thing fps settings are not going to solve the performance problem. Can phaser be instructed not to render the canvas if there was no change?

Share this post


Link to post
Share on other sites
On 6/30/2018 at 7:39 AM, mariannoga said:

Seriously? 

Well, that clarifies one thing fps settings are not going to solve the performance problem. Can phaser be instructed not to render the canvas if there was no change?

Think melonjs has a feature like that. Provide a test case!

Share this post


Link to post
Share on other sites

Ok then. If these are the answers then I conclude you guys are doing everything fine and I must be asking wrong question. Otherwise every single game in Phaser would be botched. Why is my CPU spiking when the game is not doing anything? Hard to believe it is just due to canvas rendering. 

Share this post


Link to post
Share on other sites

I think that in Phaser, they have a func call update() { }. 

This function work as a timer run with 0 delay. So when develop game based on Phaser just remember that you should avoid put many logic code inside update() func and everything will be fine. 

 

Share this post


Link to post
Share on other sites

I have been playing with my pet project in Phaser3 recently and I tried different things in order to improve performance. Here are some numbers that you might find interesting.

As previously it is a tile based scene. The map is an 80x50 tiles each 16x16 pixels. The tests have been done for 2 layers tilemap to keep it simple. I tried few approaches including mapping 2 layer map to a texture and rendering as an ordinary image. It's quite surprising which approach had best performance. Screenshots were off for purists. Update is bailing out if rendered once. Each time rendered image is exactly the same. Comment if you like.

  1. Phaser3 Tilemap with DynamicTilemapLayer. Each tile rendered with putTileAt in a for loop. CPU Usage around 50%.
    this._tileMap = this.make.tilemap({
    	tileWidth: 16,
    	tileHeight: 16,
    	width: 80,
    	height: 50
    });
    
    ...
    
    this._layers[A].putTileAt(t, x, y);

    1263261988_Screenshot2019-02-05at20_30_11.thumb.png.e4aded5c52137d57b1fa44f5025e87cc.png

  2. Phaser3 RenderTexture with addToScene=false. Each tile rendered with drawFrame in a for loop. Output with addImage at the end. With this approach CPU usage is around 10-20% but the computer is surprisingly unresponsive, despite lower CPU usage than in previous test. How can rendering 1 image be so intensive?
    const config: RenderTextureConfig = {
    	x: 0,
    	y: 0,
    	width: this._WIDTH*16,
    	height: this._HEIGHT*16,
    };
    this._rt = this.make.renderTexture(config, false);
    
    ...
    
    this._rt.saveTexture('map');
    
    ...
    
    this.add.image(0, 0, 'map').setOrigin(0, 0);
    495178198_Screenshot2019-02-05at20_20_55.thumb.png.399e5791e32060b310ae3c5b622fe0d1.png
  3. Phaser3 RenderTexture with addToScene=true. Each tile rendered with drawFrame in a for loop. CPU usage is negligible - 2-3%. By far the best approach.
    const config: RenderTextureConfig = {
    	x: 0,
    	y: 0,
    	width: this._WIDTH*16,
    	height: this._HEIGHT*16,
    	};
    this._rt = this.make.renderTexture(config, true);
    
    ...
    
    this._rt.drawFrame(spritesheet, frame, x, y);
    

     

910081908_Screenshot2019-02-05at20_10_38.thumb.png.83c17f461003cf6053e4d88ed9d702f9.png

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.