Jump to content

What is wrong with Phaser3 performance?


mariannoga
 Share

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

Link to comment
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.

Link to comment
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.

Link to comment
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

Link to comment
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?

Link to comment
Share on other sites

  • 4 weeks later...
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!

Link to comment
Share on other sites

  • 3 weeks later...

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. 

Link to comment
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. 

 

Link to comment
Share on other sites

  • 3 weeks later...
  • 2 months later...
  • 2 months later...

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

Link to comment
Share on other sites

  • 2 years later...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...