What uses less memory: strings or numbers (bit32)?

Hello, guys. I today tried to optimize my mine generation system in terms of memory, because it used in 1 minute 1 GB. For this, I tried to switch from Strings to Numbers in bit32 format. I think, that 1 string symbol uses 8 bits, so for simple word like “Stone” it will use 40 bits, and new bit-32 system will use only 8 bits per material.
So, Previously, I used system like this:

Chunk[X][Y][Z] = {
Material = "Stone",
Health = 3,
Tags = {},
}
--[==[
This system, on Z-axis has 16 values
--]==]

And after, I changed this system a lot:

BlockTypes = {
[0b_0000_0000] = "Air",
[0b_0000_0001] = "Stone",
} <-- start of script, to not forget what code is which material
...
...
...
Chunk[X][Y][Z] = {
Material = 0b_0000_0001_0000_0001_0000_0001_0000_0001,
Health = {1, 1, 1, 1},
Tags = {{}, {}, {}, {}},
--[==[
This system, on Z-axis has 4 values, because I use only 8 bits per
material, so if I need get block material, I just "cut" 8 needed bits
from Material, and use them.
Also, because of this material system, I did for Health and Tags array
consisting out of 4 variables.
--]==]
}

But, when playtesting in studio, I received strange result - ABSOLUTELY no diffirence in memory usage! (Only thing improved was speed)
And this leaded me to ask here question - is using bit-32 to write 4 values actually use less memory than Strings?

2 Likes

The memory usage you are experiencing comes mostly from all the parts, not from little things like using a string over a number. Though numbers are a lot faster than strings, I’m not too sure what you are doing with the weird 0b_0000_0000. You don’t need to do any of that.

local Materials = {
    Air = 1;
    Stone = 2;
}

Chunk[X][Y][Z] = {
    Material = Materials.Stone,
    Health = 3,
    Tags = {},
}

When you send the data to the client, the client can decode it from number to whatever material you want. This’ll improve the speed, lower the bandwidth required to send all of the data, and possibly lower the memory a little.

2 Likes

Maybe you remember my situation, where I use 8D arrays, trying combat 1GB per minute and etc.
When I looked at Console, I saw that Part usage was only 60-80 MB, while LuaHeap >= 700 MB and Script was >= 300 MB. SO parts aren’t really source of big memory usage.
Only thing that I think may harm memory is string usage, so I made system to make Materials defined by IDs. MAYBE there’s something other, but IDK what really…
This 0b_xxxx_xxxx is used for:

  1. Saving memory, because just numbers in lua use 32+ bits
  2. I think, that every symbol in String uses 8 bits ← maybe wrong statement

So, I did system where I save 4 materials in single number value, so I use 8 bits per material, and then, when I need, I’m getting that 8 bits which I need, and use them to define material.

1 Like

The tables are likely causing most of the memory usage.

Instead of nested tables, you could use

Chunk[X*size*size + Y*size +Z]

Additionally, something like this:

materials[i] = materialNumber
health[i] = healthData
tags[i] = tagData

Why would bit32 only use 8 bits? It has 32 bits.

Why are health and tag data tables? What do they store?

2 Likes

Is this in studio or in the client? Studio tends to eat more memory than the client

Sadly, studio. I can’t test it because of Roblox Byfron system, which blocks me on windows-7 from Roblox Player.

1 Like
  1. I think, that every symbol in String uses 8 bits ← maybe wrong statement

Each character in a string takes 8 bits, so for the word “Stone” it will take 40 bits.

0b_xxxx_xxxx

I only now realized that that’s possible :sweat_smile: in Lua.
Though you can just keep it at regular numbers, no need for the bit representation. It won’t lower the memory usage of each number anyways, all numbers are 32 bit.

2 Likes
  1. I can’t do thing like that because my system is infinite, so I can easillly run out of size.
  2. bit32 use 32 bits, but I use that 32 bits for 4 diffirent blocks, so each block use only 32/4 = 8 bits of memory
1 Like

Depending on how many types of blocks your game has, you could try holding multiple blocks in a single number? It’d be like encoding all of it in a single number while still keeping all the information you need.

1 Like

That’s exactly what I’m trying to do, and for this I use that bit32.

Also, I asked ChatGPT about some memory questions rn, and it told me that tables use 128 bits when created. So, most likely, I cut a lot of memory usage on bit32, but also increased it on tables, representing tags and health of blocks.

1 Like

You could switch from a dictionary to an array. It should look like:

Chunk[X][Y][Z] = {
    1, -- material enum
    3, -- health
    {} -- tags
}
2 Likes

Actually, removing tables for Health and Tags reduced memory usage BY HALF! So now it uses only 500MB (Still a lot, but it’s very good cut). But I need find way to make Tags…

1 Like