Mac OSX Memory Leak on Game Restart Caused by Persistent Rooms and Objects?

tylorlilley

Member
Hey all - I was hoping to get some clarity on the persistent rooms/objects feature. Are persistent rooms/objects not garbage collected upon calling game_restart()? Is there a way to manually garbage collect them if not?

After much digging, I determined the source of a memory leak in my project. It seems to be because when the game is restarted the persistent rooms/objects are not destroyed/collected, and that causes the memory size to slowly grow with each restart. I performed a simple test with a brand new blank project in order to arrive at that conclusion. In the new project I created:

* An obj_controller object that calls restart_game(); on a keypress of enter.
* A single room with the above obj_controller object in it.

To test this, I ran the game with the debug window open and hammered the enter key to continually restart the game (like 20+ times). I watched for if the total memory allocated increased when I did so or if it stayed the same over time. When neither the room nor the object was flagged as persistent, the total memory used did not increase. However, when either the room OR the object was marked persistent, the total memory DID increase with each restart. Is this really expected behavior? Is the game_restart(); function supposed to leave some garbage behind concerning persistent objects?

To go one step further in my testing, I tried to see if I could manually unflag these rooms/objects and get them to be collected appropriately on game_restart(). To do so, I added to lines of code above the restart_game(); line on a keypress of enter, so that the whole event looked like this now:

GML:
room_persistent = false;
persistent = false;
game_restart();
When testing this way, the memory allocated did NOT increase, so this seemed to work. Testing with out either of those lines commented out showed that the memory DID continue to increase over time, as expected. This seems to imply that one solution to this issue is to manually go through and unflag all of the persistent rooms and instances of persistent objects to make them not persistent anymore. However, that is a lot easier to do when there is only one object or room in question like in this demo, but much harder to do in a project with more of them. I am not sure how I would be able to get a list of all the persistent rooms/instances in order to manually set their flags to false without potentially missing any. What's more, the room_persistent flag seems to only interact with the active room, so such apiece of code would have to involve visiting every room in the game to mark them not persistent anymore before calling game_restart(); and that just seems... extremely heavy handed, if nothing else.

I was not able to attach the .zip containing example project I created to demonstrate the issue to this post, but it should be very simple to recreate based on my above description if you wish to try it for yourselves. Thank you so much in advance! This memory leak has been a huge pain to track down and I feel closer to solving it than ever now that I know it is being caused by the persistent instances/rooms outside not being destroyed upon a game restart. Any advice/help you can provide would be very much appreciated!
 

gnysek

Member
Are persistent rooms/objects not garbage collected upon calling game_restart()?
According to manual, it's hard to say. It says nothing about persistent things, but it's stated, that if you manually change any resource property, it will remain. Since you're setting room persistence to false, from what I understand even after restart, it might not be persistent anymore (except you again set it's persistence to true somewhere).

So there's either memory leak, or when using persistence some additional RAM is reserved to support this feature (more than needed, cause OS sometimes try to predict future usage too), and when calling room_persistent = false; you're forcing to free that part of memory, and it looks like GM uses less of it now, but remember that this room is probably not persistent anymore even after game restart, so it requires less memory.

I would try to report it to helpdesk, as it indeed looks suspicious. They will either confirm a bug, or explain it (or even add a manual entry) - and then you can share with us, so people searching for similar problem would find answer in future :)
 

tylorlilley

Member
Thank you very much for your reply!

I would try to report it to helpdesk, as it indeed looks suspicious. They will either confirm a bug, or explain it (or even add a manual entry) - and then you can share with us, so people searching for similar problem would find answer in future :)
Okay - I submitted a ticket and will update here if there is a response on that front. I was not sure if this was a known issue or an actual new bug to investigate which is why I posted here first, but you are right that submitting a ticket is likely still the fastest way to answer that question.

According to manual, it's hard to say. It says nothing about persistent things, but it's stated, that if you manually change any resource property, it will remain. Since you're setting room persistence to false, from what I understand even after restart, it might not be persistent anymore (except you again set it's persistence to true somewhere).

So there's either memory leak, or when using persistence some additional RAM is reserved to support this feature (more than needed, cause OS sometimes try to predict future usage too), and when calling room_persistent = false; you're forcing to free that part of memory, and it looks like GM uses less of it now, but remember that this room is probably not persistent anymore even after game restart, so it requires less memory.
Just to be clear, I am not wanting/expecting rooms or instances to persist after game_restart(). In the example where I am directly setting the persistent flag to false, I am doing so right before calling game_restart() and there does not appear to be any memory leak. But I am never setting it to true again! Its only set to true in the UI by clicking the persistent checkbox before running the game and not set to true at runtime during this example.
 

gnysek

Member
So from what I understand, if you set them to not persistent and then restart game, they still won't be persistent anymore, as resource settings aren't reset on game_restart(), so would be good to manually re-set this setting for each room after restart.

Ideally, on game_restart() their content (instances) should reset to initial state, but settings from IDE should remain (if not changed in mid-game), that's how I understand manual. Still, it would be great to get more detailed list of what's global and what's not here, as that's mystery to me at this point.
 

tylorlilley

Member
So from what I understand, if you set them to not persistent and then restart game, they still won't be persistent anymore, as resource settings aren't reset on game_restart(), so would be good to manually re-set this setting for each room after restart.
Ah, I understand what you are saying now - thanks. I have yet to try to implement any fixes into my main project so that would definitely be something I'd need to consider if trying to fix this memory leak there!
 

Roldy

Member
I would think this is a bug. From manual:

[...] however if you restart the game (with, for example, the game_restart() function) all persistent objects will be removed and only exist when created again by the game.
A couple things to note about persistent rooms.

Turning room persistence on:
  • Room persistence cannot be turned ON while it is the current room
  • Room persistence must be enable before entering the room
Turning room persistence off:
  • Room persistence cannot be turned off if the room has been visited (and is now persist in memory)
  • Room persistence can be turned off (via room_set_persistence) only if the room has not been visited, or...
  • Room persistence can be turned off if it is the current room
In fact game_restart is about one of the only ways to turn off room persistence without going back to the room once it has been visited.
 

gnysek

Member
Good that I'm avoiding using game_restart() and only one main object is persistent, as it seems that games with persistance shouldn't be restarted at all, or weird things might happen.
 
Top