Which takes less memory? nil or false

I’m doing some data saving and I was wondering which data type would be more efficient.
I’m fairly sure that nil takes up less space, but I want to be sure. Does know of a decent way to find out for sure?

I’m pretty sure nil takes less memory because it’s nothingness while false is falsely, it still exists

:man_shrugging:

4 Likes

In terms of efficiency I think the difference would be unnoticeable. Technically true/false only needs 1 bit, but I think they are stored as 00000001 and 00000000. If nil were simply the absence of any data, then like I said the difference would be unnoticeable but nil would be slightly better, but if it were to be a datatype then it would probably be the exact same size as true/false or slightly bigger.

2 Likes

I believe this is the correct answer.

If you’d excuse the low-level jargon for a second; 99% of the time, stuff in memory will be byte-aligned. This means that usually the smallest unit of memory you’ll be dealing with would be one byte. It’s perfectly possible that the Luau VM can represent true, false or nil values within a single byte, since these data types are very simple. Therefore, it’s not unreasonable to assume that they’d all be represented by single bytes in memory, making their footprint the same. Alternatively, I could see true/false being an extra byte in length if the value is stored separate from the data type.

But you shouldn’t really worry about this anyway, since the difference would at most be a single byte, and more likely would be no difference at all. Use what makes most sense semantically for your code.

5 Likes

Both take the exact same amount of memory. Lua primitives (not GC’d) are stored in an union, so all values take 8 bytes (canonically) in the stack. These values are not dynamically allocated, so when passed around so it’s not the same as a table or string which are a reference on the stack.

In short: nil, booleans, numbers, and I hear that Vector3s soon all take the exact same amount of space.

Or well in the case of data saving, at the moment it’s in JSON so good luck.

6 Likes

Yeah - look here ^. So true and false both cost one Byte (+ whatever compiler, Roblox adds - Autterfly says 8 bytes) as once you break it down to machine code it’s 1 or 0. while nil literally costs nothing as you’re telling it to forget said value.

Update: Fixed the one byte to account for roblox assigning 8 bytes to all values which in my experience is a bit odd but there we go. In practise you don’t need to worry about this as the perfornace difference is negligible and should only be considered (briefly) in a language such as C++.

nil , booleans, numbers, and I hear that Vector3 s soon all take the exact same amount of space

When you say numbers, are you referring to integers or floats?

Integers and floats are the same thing in lua.

Also, is there any way we can actually measure the difference though?

Newer versions of lua (starting from 5.3 I think) have a math.type function, which returns the type of a number (as a string), either an integer, or a float. And more precisely, they are doubles and not just floats.

Also autterfly already pointed this out, but remember that Datastore :JSONEncode()s internally, so you don’t care about physical size, but string length. httpservice:JSONEncode(false) would be a simple false, httpservice:JSONDecode(nil) would be a null, 1 character shorter. If you’re really desperate, save a 0 instead of a nil or false.

@jeditcdisback sorry for the nitpick, but binary isn’t necessarily machine language. Machine langauge is cpu instructions written in binary.

3 Likes

When you say data saving, do you mean working with DataStores? If so, storing the value as nil will remove the key entirely from the JSON string which is saved, if you have some sort of tabular format

e.g.

local Data = {
    Kills = 10,
    XP = 1000
    SpecialItems = nil
}

becomes JSON encoded to {"XP":1000,"Kills":10}

As opposed to this,

local Data = {
    Kills = 10,
    XP = 1000,
    SpecialItems = false
}

which becomes JSON encoded to {"SpecialItems":false,"XP":1000,"Kills":10}

2 Likes

Sixteen bytes actually. 5.2 took a brief departure to introduce a mode where all values are eight bytes using NaN tagging like LuaJIT, but had to backpedal in 5.3 due to compatibility issues and the need to be able to store a 64-bit integer (although technically they could have used 32-bit integers but I suppose at that point the advantage of integer types becomes even more dubious).

6 Likes

All good, I understand the itch and apologies for the mix up there.

1 Like