I found that searching for this answer confusing and not well documented.
In JavaScript you have a MAX_SAFE_INTEGER
defined as 2^53 - 1
I did discover an article that put such large numbers into perspective however they focus on 2^64
. And JS uses a smaller number. Most birthday paradox calculators lack the ability to scale to that number.
Why is this interesting? I found myself debating with developers about the use of a UUID(v4) for unique IDs in their web apps. By comparison a monotonic counter globally used in a single web app would have an entire 2^53 - 1
space of unique values per tab session. I’m interested in understanding the trade off of the exhaustion of values for a monotonic counter compared to the collision probability of UUIDv4.
2
Answers
The calculation to find the time to exhaust
MAX_SAFE_INTEGER
(in years) should be pretty straightforward if we assume we’re working with a monotonic counter that increments once per second.MAX_SAFE_INTEGER
(2^53 – 1) = 9,007,199,254,740,991assuming the counter increments once per second), which would be
~31,536,000 seconds. So, 9,007,199,254,740,991 / 31,536,000 =
285,616,414.7 years to exhaust.
Frame challenge
You are not really taking in the big picture.
Out of idle curiosity, I tried to figure out what is the collision chance after generating 2^53 – 1 UUIDs. But then I thought about it a bit more: if you really have that many UUIDs, are you not doing something incorrectly?
Some back of the napkin maths:
9 trillion UUIDs
Each UUID is 128 bits1, so
One quintillion bits. In bytes
144 quadrillion bytes. In kilobytes:
144 trillion kilobytes. In megabytes:
144 billion. In gigabytes:
144 million. In terabytes:
144 thousand terabytes. In petabytes:
144 petabytes. That must be stored by the page. If they were not stored (say, you take one item, process it, give it an ID, then stop working with it) then there would be no issue with collisions. This is simply unfeasable amount of memory.
Let us say that you do not generate 2^53 – 1 UUIDs. Perhaps you only do half (72 petabytes), or a quarter of it (36 petabytes). That is still within the petabyte range. Way too large for any page.
We could look at it from the opposite direction – given some amount of memory how many UUIDs can we fit in it, which we can calculate by dividing the bytes by 16 (128 bits * 8 to get bytes). If we go with a whole lot memory for a single page 10 GB (10 000 000 000 bytes) we get:
625 million UUIDs. It is still a lot of memory to consume. And let us compare how that number compares to Number.MAX_SAFE_INTEGER:
It is almost half the length.
I think all of these numbers really just show that if you ever have to consider UUID vs Number.MAX_SAFE_INTEGER – then do not. It is not worth it, UUID is unfeasable at that point.
1 128 bits in raw form. As a string, it would be larger. But using the bits for easier calculation. Also, I assume it is UUID v4 as the most widely used one.