drawTextInRect docs need to contain a warning :)

I was going to reply to this thread (and I wish I'd seen it earlier!) but the forum software cautioned me about necro-ing a thread so old, so making a new one here.

At about 80% done and 35K lines of Lua code (not counting comments), our Playdate game is nearing completion... and a friend loaned me an actual Playdate console so I could begin testing on actual hardware (finally!) before mine arrives later in the year.

And a good thing, too... doing a top-to-bottom overhaul due to simulator-vs-hardware differences (font legibility, size of actors on screen, etc.) as a result.

The main game didn't have any performance problems, but we also have 8 or 9 minigames - and some of those were having real performance problems.

Long winded intro, but... as the title says, a good portion of the performance issues were pinned down to use of drawTextInRect - not for huge swaths of text, but just for lining up a couple-to-maybe-four lines of text here and there.

Ex: one of the minigames is a Lunar Lander clone... on the upper part of the screen we have a HUD with something like this for values that are constantly changing:

SCORE: 0                                              ALTD:   32.7
 FUEL: 5000.0                                         VVEL:  -10.5
                                                      HVEL:    6.7
                                                      ANGL:    0.0

Originally this was implemented as four vertical blocks of text containing "SCORE:\nFUEL:" and "$1\n$2" and "ALTD:\nVVEL:\nHVEL:\nANGL:" and "$1\n$2\n$3\n$4"... a few gsub's and four drawTextInRect's later we had a nicely aligned real-time HUD. Solid 30fps in the Simulator.

Once on actual hardware and there was a noticeable hit to improvement, though - and not necessarily steady... sometimes there would be hitches/hiccups as well (wasn't due to the GC kicking in, I think... I tried turning the GC off and it didn't make any difference).

After a full day of much head-scratching and process-of-elimination I nailed down the performance hit to just a few uses drawTextInRect. Replacing them with a plain 'drawText' was a major improvement in both framerate and steady execution. Finally resolved just to not use it at all, even though that column of numbers above looks better right-justified - even using just one drawTextInRect with right-alignment for that single column of four numbers caused noticeable lag and stutter on actual hardware.

I'm hoping that the drawTextInRect implementation gets some Panic dev-love at some point - it's a really useful thing to have, but it's not practical if framerate/steadyness is a concern (like in arcade game HUD vs just showing general UI text where even going down to 10fps wouldn't be noticeable). Barring that, maybe the drawTextInRect docs should have a warning about performance issues :slight_smile: .

In the hopes that it will help, I put together a test case. There are 8 blocks of text with the lines separated by '\n' - initially they're all drawn with a plain 'drawText' call, but as you tap the 'A' button one by one they instead use 'drawTextInRect' with a right alignment. You can see the hit to framerate as things progress:

If high/steady framerate is a concern then just one or two uses of drawTextInRect can put you over the edge into 'not playable'.

Test case (source and .pdx attached).

Be well! :slight_smile:
TextInRectPerfTest.zip (31.5 KB)

8 Likes

Thanks for pointing this out! I'll check it out in the sampler, but this looks like something we need to move from a CoreLibs Lua implementation to C code in the main firmware.

10 Likes

Wow, thanks for this reminder that drawTextInRect has big performance implications. I have a 200+ item list where each cell was rendered with drawTextInRect, and replacing it with drawText gave me a 10-15 fps boost in performance on device!

4 Likes

I'm hitting this as well. My otherwise solid 30fps game drops to 8-13fps when I'm lining up a bunch of text for one scene. I'm going to need to refactor that code to render differently as it's unusable in the current state.

Just wanted to +1 to the notion of moving that function to C or at least publishing some best practices in the docs.