Is this a bad practice?

Hello,

I’m currently “designing” (for lack of a better term) a table structure for storing player data. I am sorting certain pieces of data in an array. At certain points, values of the array are destroyed, in which case I set them to nil. When it comes to adding new values to the array, I am not placing new values in this open space, and I am not shifting existing values down, I am leaving the gap. Is this bad practice? Could it be considered a memory leak?

P.S: When the player disconnects, the array is being cleaned up and values are being shifted down to remove gaps.

You should use profile service to save player data. It has a nested table structure which handles session locking, memory leaks and is quite efficient and safer than the normal datastore service. You can actually use it for any data in fact, example: group owned houses
Save your player data with ProfileService! (DataStore Module) - Resources / Community Resources - DevForum | Roblox
Kind of like an enhanced version of DataStore2

I’m using profile service for saving the data. In my system though, I need the indicies of the values to remain the same, so I am leaving the gaps where indices are just set to nil. My question is just whether that practice is bad, or would be considered a memory leak.

No I do not think so
char limit

The issue with arrays with (a) gap(s) is that when you iterate over them with ipairs the iteration stops at the first gap.

local a = {1, 2, 3, 4}
a[3] = nil
for i, v in ipairs(a) do
	print(i, v)
end

--1 1
--2 2

pairs remedies this but then the order of traversal becomes undefined.

2 Likes

Setting it to a pre-defined “blank” value, such as 0, would allow ipairs to work as intended, right? If so, is there a concrete yes or no as to whether this is a safe practice? My only worry is that if a player made lots of edits to their data during the play session, these blank spaces would add up and it would make the array exceedingly long. Would the values in the indices take up much space though, or would it only really be the length of the array which really effects performance?

Yes, if you set it to anything but ‘nil’, I’d advise ‘false’, ipairs will work as intended.

local a = {1, 2, 3, 4}
a[3] = false
for i, v in pairs(a) do
	print(i, v)
end

--1 1
--2 2
--3 false
--4 4
1 Like

It may or may not be a memory leak depending on the exact details of how roblox puts values in the hash vs array part of the table. I would lean towards it is unbounded memory usage.

Unless your data is tens of thousands of bytes, I’d bet its fine.

It sounds like you might want a set to store your data, though.

Instead of this:

local data = {
  { name = "a" },
  { name = "b" },
  { name = "c" }
}

You do this:

local data = {
  [{ name = "a" }] = true,
  [{ name = "b" }] = true,
  [{ name = "c" }] = true,
}

You can still loop through easily with for data in pairs, and you can constant-time lookup if something is in the set or not. You can delete without wasting memory by setting an object to nil.

When it comes to store this data, you could turn it into a continuous array, and build the set again when you load it.

1 Like