Is Roblox's UUID (GenerateGUID) system actually gaurenteed unique?

Allow me to elaborate. Roblox has a GUID function which it says creates a 36 digit unique string. As I have heard from some others, UUID systems may not work by checking if an ID already exists, but by relying on the fact that the chance that two UUIDs are the same is astronomically low.

With that in mind, I am aware that despite the low odds, generating and saving thousands of UUIDs a day could increase the risk of collision. In order to eliminate this risk, storing all used UUIDs is necessary. What I am unsure of is if this is what Roblox does. If Roblox does do this, then in what scope does it save a blacklist of UUIDs? All of Roblox? Per game? Etc. Part of the reason I believe Roblox may save a blacklist of UUIDs that have been generated is that (and I apologize if this is a naive assertion) I found this wiki page about “GuidRegistryService”.

So, does GenerateGUID actually ensure that the returned ID is unique, or does it rely solely on the low chance of a collision?

And please, do not try to tell me this question doesn’t matter because the chance of a collision is 1 in a bajillion. I am here for a definitive answer, not just the obvious. Thanks.

11 Likes

The likelihood of you getting a duplicate UUID is near zero.

The probability to find a duplicate within 103 trillion UUIDs is one in a billion

To answer your question, it is not guaranteed to be unique, there is a very small possibility you’d encounter a duplicate.

7 Likes

With that in mind, what does GuidRegistryService do?

1 Like

I’m not sure but I’d assume it’d be for preventing duplicate GUID’s. I may be wrong though.

That’s what I am trying to determine, whether or not Roblox is preventing duplicate UUIDs with GuidRegistryService. Perhaps @zeuxcg would know?

The probability of getting a duplicate ID exists, it’s just so low making it mathematically impossible for it to occur.

To answer your question: I do not believe roblox stores each result. If this was the case it would only be done per game, and not persist between sessions.

I also did a quick test on this theory:

(Without storing them)
img

Code
local HttpService = game:GetService("HttpService")

wait(10)

local initialMem = collectgarbage("count")

print("Initial memory:", initialMem)

for i = 1, 1000000 do

HttpService:GenerateGUID(false)

end

local currentMem = collectgarbage("count")

print("Memory after generation of IDs:", currentMem)

print("Difference:", currentMem - initialMem)

wait(60)

local currentMem = collectgarbage("count")

print("Memory after waiting for GC:", currentMem)

print("Difference:", currentMem - initialMem)

(Storing them)
bild

Code
local HttpService = game:GetService("HttpService")

local list = {}

wait(11)

local initialMem = collectgarbage("count")

print("Initial memory (Stored):", initialMem)

for i = 1, 1000000 do

local id = HttpService:GenerateGUID(false)

table.insert(list, id)

end

local currentMem = collectgarbage("count")

print("Memory after generation of IDs: (Stored)", currentMem)

print("Difference:", currentMem - initialMem)

wait(60)

local currentMem = collectgarbage("count")

print("Memory after waiting for GC: (Stored)", currentMem)

print("Difference: (Stored)", currentMem - initialMem)

As you can see there is barely any difference in memory. If we store the id’s in a table however, the memory increases by a lot. Because of this we can be relatively sure that the id’s are not stored. (at least not on the server)

1 Like

So some napkin math for ya.
Each char in a uuid is a hex 0-9 A-F.
Internally each char is a byte so a uuid is 32 + 4 (with the - ) bytes. (There might be a null byte but we’ll ignore that.)

With 16 different combos in a char and 32 slots that’s 3.4e38 combos (100 is 1e2, 1500 is 1.5e3)
3.4e38 combos X 36bytes is 1.2e40bytes or 1.2GB

So not actually too much memory

1 Like

No, Roblox does not store results of this function nor guarantee their uniqueness. Here’s how you’re meant to use it:

  1. Generate a GUID
  2. Check if it’s in use (if it is, go back to 1)
  3. Use the GUID

The idea is that it’s cheaper to check if a generated ID is already in use rather than attempt to coordinate a strictly-ascending ID system for something that doesn’t necessarily need ordering. Of course this will gets harder over time as more and more IDs are used up, but this takes a loooooong time and adding more bits to the IDs is trivial.

GuidRegistryService is for something completely different, likely related to platform analytics.

9 Likes

I made a script a bit ago that guaranties uuids for all instances.

It could be modified to be just a uuid guarantor. It works off the principle that you can use the uuid as a key to see if it exists rather than searching a big list.

3 Likes

Thanks. I did some testing and generating UUIDs is extremely fast, even when a million IDs are stored as used, adding an additional million only took me about a second. This seems to be the way to go.

1 Like