I’ve heard about Luau introducing typing but I haven’t been following it too closely. Does typed luau mean I can specify specific data types for my numbers to save space in memory? Does typed luau optimize memory use with its extra knowledge about what type everything is (since it has less to infer)?
For example, I’ve got a really massive set of data stored in script memory which contributes up to 100MB of memory. A massive chunk of the data is many, many positive integers going up to ~30k. If I can specify that these values are all 16 bit unsigned integers (which represent values from 0-65,536, completely sufficient for my purpose), I should be able to shave off a quarter of the memory occupied by these numbers (since I believe Lua traditionally stores all numbers indiscriminately as doubles which use 64 bis).
I know this type of aggressive optimization may sound silly for a Roblox game but it matters very much to me and I suspect as my game grows in resource demands, I will need to find new ways to shave on costs. Any news on this regard?
Does typed luau mean I can specify specific data types for my numbers to save space in memory
Nope, there is only 1 number type in Luau called “number” which is the same double-precision floating point number we’re all used to.
Does typed luau optimize memory use with its extra knowledge about what type everything is
Potentially in the future some optimizations are coming but I don’t know if there will be a point in time where there are “two modes” for the VM (one that uses tagged unions for lua values, among other structures that are generally “heavier” and one that doesn’t) since non-strict code can still be interacted with from strict code I believe.
But in your specific case, you can pack your data into a string where each 2 characters make up your integer. If you went from an array of numbers (~16 bytes per value I believe) to just storing each value continuously in a string (~2 bytes per value) you could easily see savings up 4x.
To add to @jakedies’s answer, ROBLOX recently added string.pack/unpack/packsize. Undocumented currently, but that link explains them. Basically, it lets you use strings as arbitrary chunks of memory. For your case though, it seems like you might actually want to implement your own byte-packing-in-strings with string.byte.
Note that data stores don’t let you store characters >127 in strings.
More importantly maybe, consider that you might not need to optimize . 100 megs isn’t that much. As I write this, my tasks manager RAM looks like this:
chrome: 600 MB
visual studio: 400 MB
teams: 350 MB
vs code: 300 MB
spotify: 150 MB
outlook: 150 MB
windows explorer: 60 MB
If your data is just in memory and you’re not trying to send it over the network as a whole, you don’t really have an issue until you find out that you do, imo.
I appreciate the suggestion about using chars to pack in bytes of data, I’ve already tried that and unfortunately it did not work because when you create a new string in Lua, a decent amount of extra memory is also reserved (for some reason). I did a benchmark where I stored 16 bit numbers in the regular number format, versus storing them in 2 char long strings (16 bits), and the numbers used up substantially less memory. I believe I’ve even done a test where I store all of my numbers into one giant string; same thing.
[Note that when I say 16 bit number, I mean values that can be represented in 16 bits. Of course, I don’t have the ability to store a number in 16 bits, so these “16 bit numbers” are being stored in the typical 64 bits.]
local n = 1000
do
local start = collectgarbage("count")
local s = string.rep('ab', n)
print(collectgarbage("count") - start)
end
do
local start = collectgarbage("count")
local s = table.create(n, 0)
print(collectgarbage("count") - start)
end
Prints 4 KiB using the string method and 16 KiB using tables, which is a savings of 4x.
It’s possible that you were constantly creating new strings by doing something like s = s .. packshort(i) . The memory used from “old strings” are not immediately GC’d so you might see increased memory usage in such a case (but eventually, they will be GC’d).
It’s been a long time since I did that first test, so there is a good chance you are right. I would’ve definitely waited for a decent amount of time, but maybe the GC was taking its time then.