Ancurio / mkxp

Free Software implementation of the Ruby Game Scripting System (RGSS)
GNU General Public License v2.0
525 stars 137 forks source link

Game keeps getting slower #162

Closed pulsejet closed 7 years ago

pulsejet commented 7 years ago

In several games, gameplay keeps getting slower continuously till it is unplayable. After restarting the game, it is back to normal.

sorlok commented 7 years ago

That's quite odd... can you give some examples of games? Also, does it happen with all games? And how long does it take (minutes? hours?) for a game to become unplayable after you restart it?

pulsejet commented 7 years ago

Definitively in Aveyond 4, sometimes in Exit Fate (free). It usually takes ~20 minutes to get slow.

Ancurio commented 7 years ago

How does RAM usage look at start (/ after 5 minutes of gameplay) vs when it gets slow? Any other clues that would shed a light on this? Just "it get's slow" doesn't really tell me where to look.

pulsejet commented 7 years ago

Alright, will try to get some stats on what's happening tomorrow. I've currently found a workaround that if I almost kill the game (fall back to the main thread destroying everything) and restart the game from there, then the lag is not present.

khkramer commented 7 years ago

There's probably a script constantly running and filling up memory then, I've never had any issues with MKXP itself being the cause of any slowness.

sorlok commented 7 years ago

@radialapps To add to @khkramer's comment, I've got a released game that has 10+ hour single sessions with no long-term accumulation of slowdown. (Not saying mkxp doesn't have bugs, just adding a data point.)

Sprite leaks are very easy to introduce accidentally. To help debug them, my copy of the mkxp repository has a super-hack function called "specialSpriteCount" that returns the total number of sprites the system knows about: https://github.com/sorlok/mkxp/blob/ld_hacks/src/sharedstate.cpp#L436

It may be useful for you to put a Sprite at the top of your Scene_Map (or whatever scene you observe the slowdown in) that reports the maximum sprite count over time (gained by sampling "specialSpriteCount" periodically); this number should stabilize after a few minutes of play, and if it keeps increasing then you know you've got a leak.

pulsejet commented 7 years ago

I had forgotten about this ... thanks for the reminder =P

Still haven't got to profiling, but RAM usage seems stable. One observation I could make was that the lag was highly personified when compiled for arm (Android for now, though I could try on a raspberry pi when I have time).

Another was that if I turned off counting the text area as tainted in bitmap.cpp by commenting this line (I think this was the one, will confirm soon), then the lag reduces to a (very) large extent, which makes me suspect SDL_ttf.

I'll try to get some more information as soon as possible.

pulsejet commented 7 years ago

I've narrowed this down to megaSurface with SubImageFix. Whenever the game enters a map which uses megaSurface (and SubImageFix is true), it continues to remain slower even after leaving the map.

pulsejet commented 7 years ago

@Ancurio, can you check out this commit? : https://github.com/radialapps/mkxp/commit/e0d97d42dd59b6cb048e97fe7a4612ad4f53aef7

For some reason, allowing textures to reduce in size leads to a huge (HUGE) performance benefit on Android while rendering text, especially when megaSurfaces are being used. As a novice to OpenGL, I don't really understand why this should be, but I've tested it on three devices with different GPUs to similar results.

Ancurio commented 7 years ago

@radialapps Ohh right I just connected the dots that you are working on mobile; of course completely different rules apply on platforms where RAM and especially video RAM are not abundant. Most of the code in mkxp doesn't take that into account, so there are lots of "allocate once to amortize allocation cost and keep around" chunks of code scattered around. For the general purpose texture from shState (that's what it is, sorry about the atrocious function names), you could even go a step further and allocate a temp texture that you deallocate immediately after use.

Also you might want to play around with the maximum size of the Texture Pool to have unused textures be returned to the system earlier (you can also call disable() after it is created in shState to completely turn off caching).

I think if you had a way of measuring VRAM utilization, it would be easier to judge whether mkxp is pushing the device towards its limit.

pulsejet commented 7 years ago

Reducing the max size of the pool doesn't seem to have any (at least apparent) effect. Can't really find any way to measure the VRAM usage, so I guess there's no way of knowing ...

Anyway, together with disabling all text shadows, modifying the rgss scripts so that the text is drawn by the line instead of drawing every character and the couple of fixes above, I was able to get everything fast enough for my expectations. Literally, rendering a big block of text on my PowerVR G6200 that was taking ~8 seconds earlier now takes less than a second, and the game doesn't get any slower when it encounters megaSurfaces 😁

EDIT: Just for the record, RAM usage is stable and low, so is the CPU