skip to Main Content

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


  1. 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.

    1. Calculate MAX_SAFE_INTEGER (2^53 – 1) = 9,007,199,254,740,991
    2. Divide that by the number of seconds in a year (this only works
      assuming 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.
    Login or Signup to reply.
  2. 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:

    2^53 - 1 = 9 007 199 254 740 991
    

    9 trillion UUIDs

    Each UUID is 128 bits1, so

    9 007 199 254 740 991 * 128 = 1 152 921 504 606 846 800
    

    One quintillion bits. In bytes

    1 152 921 504 606 846 800 / 8 = 144 115 188 075 855 860
    

    144 quadrillion bytes. In kilobytes:

    144 115 188 075 855 860 / 1000 = 144 115 188 075 855.84
    

    144 trillion kilobytes. In megabytes:

    144 115 188 075 855.84 / 1000 = 144 115 188 075.85583
    

    144 billion. In gigabytes:

    144 115 188 075.85583 / 1000 = 144 115 188.07585583
    

    144 million. In terabytes:

    144 115 188.07585583 / 1000 = 144 115.18807585583
    

    144 thousand terabytes. In petabytes:

    144 115.18807585583 / 1000 = 144.11518807585583
    

    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:

    10 000 000 000 = 625 000 000
    

    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:

    9 007 199 254 740 991
              625 000 000
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search