Detecting Available memory on Android/iOS

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By shavlor

Hello I recently made the jump to Godot (Previously used Android Studios directly, really like Godot so far and looking forward to porting my game to iOS).

I am using Godot 3.0.6 (stable).

I have been scoring the internet and Godot’s docs trying to find a way to detect how much memory is available to be used for my game, particularly on Android and iOS as those will be my primary targets. If I missed something obvious I apologize (BTW: The Performance monitoring function for available memory will not work as I need it for release mode and it does not appear to actually return the available memory only the used memory).

The rationale for this request is as follows:
I currently am loading plenty of image files and don’t want to needless free them as reloading them can create lag and they will be used again. However, if I am getting close to the memory restriction, I can drop them and reload them later. I have run tests on my Samsung S8 and have found it can load between 1.7 GB and 1.9 GB, but I am worried about older devices and would like to make my memory cap more dynamic, thus allowing newer/better devices less loading/lagging experience.

Worst case scenario I can think of is to save the used memory now and then and if the game is not closed correctly (i.e. runs out of memory). I would set a portion of that memory as cap say 80% this would allow semi dynamic memory limits, but this approach requires memory crashes to set the limit (definitely not ideal).

I thought there may be way to do try and catch when creating my image objects to determine the memory limit, but as there is no try and catch in GDScript so I cannot use this approach.

Any help would be greatly appreciated and please let me know if you need any additional information.

:bust_in_silhouette: Reply From: wombatstampede

On Android:
Open the text file /proc/meminfo (read only). I just tried it out on my android blackberry (using totalcommander) which is definitely NOT rooted. It gives plenty of information.

Both systems have a kind of automatic memory management. So they should close unneeded apps in the background when more memory is required. This may lead to unnecessary low “free memory” values.

Thank you wombatstampede,
This is a great starting place for Android.
I have begun some testing and once I figure out a good method I will post it here. I will say that there is no one line that looks like it can be set as a threshold.

I wanted to use the line AvailableMem: XXXXXXkb
but have found that just before my game crashes it can range from 700MB to 100MB… and I would like a little more precision than leaving 600 MB on the table

I have a feeling that it might require a difference or ratio of two variables to properly predict the crashing point.

Thanks again

shavlor | 2019-01-25 05:01

Well after further investigation it appears the best line to use is the SwapTotal line.
This however does not return what is the total available memory left instead how much memory can be used in total.

Therefore by taking the difference between how much as been used:
I found using the function OS.get_static_memory_usage() does the trick just be warned that this returns a 32 bit integer and for devices with more than 2^30 bytes of memory (or 2 GB) the function will start returning negative values
so either cap your game at 2 GBs or track the used memory by checking when the signs switch and add 1 << 31 for the first switch and 1 << 32 for every following switch.

Below is the code I used to pull the total available memory, but one last note: Make sure you leave a buffer between the total used memory and the swaptotal this is because the game will try to grab the next chunk of memory before registering it as used and thus crash and am sure if I could use every byte.

I used the following code to grab the SwapTotal amount (note it is in KBs):
var fp = File.new()
var txt = “”
var utxt = “”
if fp.file_exists(“/proc/meminfo”):
fp.open(“/proc/meminfo”,File.READ)
while not fp.eof_reached():
txt += fp.get_line() + “\n”
fp.close()
var regex = RegEx.new()
regex.compile(“SwapTotal:[ \t][\d]”)
var result = regex.search(txt)
if result:
regex.compile(“[\d]+”)
var result2 = regex.search(result.get_string())
if result2:
tot_available_memory = int(result2.get_string())

Once I start development on iOS I will look into how to get the available memory located there, hopefully there is a similar approach that will work.

shavlor | 2019-02-03 05:11