Measuring available system memory with Lua

,

Posted about this in the playdate squad discord, didn't find any clear answers so asking here. What do people use to manage memory consumption on device without the use of simulator? I want to be able to log system memory (% of total, preferably) at key points in my game in order to profile how optimization changes affect memory consumption, as well as having a way for QA to view memory usage in development builds (surely this must be possible... for context, the game in question is pushing up against the limits of 16MB pretty hard so I need to squeeze everything I can out of it)

There are 2 ways I know: device info in the simulator, and collectgarbage("count"). The former works great, but requires a tethered playdate with a human paying attention to it, and isn't useful for my case.

While there are many posts on this forum detailing how to use the latter to view available memory.. it doesn't seem to actually work? collectgarbage("count"), as far as I can tell, does not return anything relating to system memory usage but rather Lua memory. I tested it with a short Lua program:

import "CoreLibs/graphics"

function playdate.update()
    playdate.graphics.clear(playdate.graphics.kColorWhite)
    playdate.graphics.drawText(collectgarbage("count") .. " KB", 100, 100)
    if(playdate.buttonJustPressed(playdate.kButtonA)) then
        mygarbage = playdate.graphics.image.new(1024, 1024, playdate.graphics.kColorBlack)
    end
    if(playdate.buttonJustPressed(playdate.kButtonB)) then
        mygarbage = nil
    end
end

When pressing A, the above code does not show a substantial increase in memory consumption, but the device info screen shows a whopping 125KB increase (which makes complete sense).

So, how do y'all get memory consumption of the device at runtime?

I'd have to run my old code to check how it works today, but collect worked for me a couple of years ago.

https://devforum.play.date/t/tracking-memory-usage-throughout-your-game/1132

But as you say this is not representative of all system memory.

Yeah this is one of the threads that confused me because I compiled for old SDK versions and ran on old simulators with no change in behavior. But I was also under the impression this used to work, probably due to the fact that I fiddled with it in the past and never really looked closely at what it was spitting out. But maybe I'm doing something wrong, curious to see what you get when you run that code above and your old code.

I'm still seeing the same reporting as I always have:

Old build (not sure of SDK)

Slightly different initial memory usage on new SDK.

New build (2.4.0)

To be clear it "works" for mine as well in the sense that it does count lua memory, but the stuff that matters, i.e. pixel data in a large imagetable, is not counted. In my game there are several megabytes of huge fullscreen animations loaded at certain times, so this results in a pretty enormous (several MB) offset between what collectgarbage returns, and the actual memory consumption, making it effectively worthless. (and even in just the small code snippet in the OP, it is effectively worthless)

So I guess my question is, how do I get that true memory % at runtime on device?

Interesting.

Given that it's a lua built-in function it should just work and count everything. Everything is a table, as the saying goes. It does count my image table data for Daily Driver (each car is about 400KB).

I'll do some more testing later on See the Sky, which loads in a 2MB image table that consumes 10MB of RAM after loading.

And I'll watch this thread to see if any more info comes to light about how the Simulator hooks RAM usage.

Thanks for checking it out. That's really bizarre. The context is in For Home, right now a typical dungeon keeps about 10MB of stuff loaded, the vast majority being imagetables, but collectgarbage only counts 700KB of it. There must be some difference in the context of where these tables are being stored that results in this. Also curious to see if anyone can confirm the results from my code snippet above to make sure it's not my setup somehow.