[SOLVED] Phaser 3 vs Phaser 2 Text Creation Performance

Hey all,
I have successfully managed to migrate a mathematical project from Phaser 2 to Phaser 3. I have deleted ~2 thousand lines of code (from keyboard, events, emitters, setOrigin, containers etc…) and everything* looks and performs so much better.

However*, for every node / circle object, I need to create 2 text objects - an ownerLabel and payoffsLabel. In Phaser 2, this method takes ~0.5ms. In Phaser 3 it takes ~10ms.

This really builds up as every line also has a label. So creating 16 nodes also creates 15 lines which results in ~30 texts and requires ~300ms on Phaser 3 vs ~15ms on Phaser 2. I can add profiling

Code (simplified):

private createLabels() {
    this.ownerLabel = this.scene.add.text(0,0, 'some text', {
      fontSize: 24,
      color: '#000',
      fontStyle: 'bold',
      fontFamily: 'Arial',
    });
    this.ownerLabel.setInteractive();
    this.payoffsLabel = this.scene.add.text(0, 0, 'some text', {
      fontSize: 24,
      fontStyle: 'bold',
      align: 'right',
      fontFamily: 'Arial',
      color: '#000'
    }).setOrigin(0.5, 0);

    this.payoffsLabel.setInteractive();
   //"this" points to the node object, which is a container.
    this.add([this.payoffsLabel, this.ownerLabel]);
  }

P2 version here
P3 version here
You can drag-select the leaves and press “N”, which will generate new nodes.

My thoughts:

  1. Object Pools? - my objects are fairly complex, with lots properties - both GameObjects and Model Objects, so I would have to create something custom pool which would take a lot of time.
  2. Bitmap Fonts? - will they be faster? Seems an overkill for an Arial font. Also, if in the future there is a requirement to change fonts, I would have to load each separately. Doesn’t seem like a good idea.
  3. RenderTexture? - tried it to no avail and also seems like an overkill.
  4. Disable rendering on creation? I have not tried this, but I do not think it will work…

I am really asking for your help on this, because I love Phaser 3 and would really like to stick with it for the future development of the project. Thanks in advance for your help!

I can’t guarantee that this is the exact reason, but it’s a common offender when making many text objects at once. To render text, Phaser has to measure the font. Because browsers don’t provide an API to do it efficiently, this is done by creating a separate canvas and counting pixels, which is a really slow operation.

I haven’t worked with Phaser 2 for a long time, but looking at the source code, it seems that it automatically caches the metrics for each font. Phaser 3 doesn’t do that automatically, so it measures the font each time you create an object. You should create one text object with the desired font, then store its metrics somewhere using text.getTextMetrics(). You can then pass this object into the text style of new Text objects to avoid measuring the font:

const metrics = text.getTextMetrics();

// ...

this.add.text(0, 0, 'some text', {
    fontFamily: 'Arial',
    fontSize: 24,
    metrics: metrics
});

Note that changing the font in any way after the text is created will make Phaser recalculate the metrics. You should also make sure that the metrics you pass come from a text object with the exact same font.

6 Likes

@Telinc1, Thank you so much. This worked perfectly! Let me buy you a beer!

I created 4 metrics constants for each of my fonts, passed them to the constructors and everything is quick again.

I tried it, but with metrics set, i got only around 5% faster render speed.