An Efficient Way to Create GUID/UUID in JavaScript

An Efficient Way to Create GUID/UUID in JavaScript

I have cerated this GUID/UUID generator, which is short, simple and efficient. This post includes explanations of the algorithm below.

The function is as simple as this:

/**
* Generates a GUID string.
* @returns {String} The generated GUID.
* @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
* @author Slavik Meltser ([email protected]).
* @link http://slavik.meltser.info/?p=142
*/
function guid() {
    function _p8(s) {
        var p = (Math.random().toString(16)+"000000000").substr(2,8);
        return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;
    }
    return _p8() + _p8(true) + _p8(true) + _p8();
}

To test the performance, you can run this code:

console.time('t');
for (var i = 0; i < 10000000; i++) {
    guid();
};
console.timeEnd('t');

I’m sure most of you will understand what I did there, but maybe there is at least one person that will need an explanation:

The algorithm:

  • The Math.random() function returns a decimal number between 0 and 1 with 16 digits after the decimal fraction point (for example 0.4363923368509859).
  • Then we take this number and convert it to a string with base 16 (from the example above we’ll get 0.6fb7687f).
  • Math.random().toString(16).
  • Then we cut off the 0. prefix (0.6fb7687f => 6fb7687f) and get a string with eight hexadecimal characters long.
  • (Math.random().toString(16).substr(2,8).
  • Sometimes the Math.random() function will return shorter number (for example 0.4363), due to zeros at the end (from the example above, actually the number is 0.4363000000000000). That’s why i’m appending to this string "0000000000" (a string with nine zeros) and then cutting it off with substr() function to make it nine characters exactly (filling zeros to the right).
  • The reason of adding exactly nine zeros is because of the worse case scenario, which is when the Math.random() function will return exactly 0 or 1 (probability of 1/10^16 for each one of them). That’s why we needed to add nine zeros to it ("0"+"000000000" or "1"+"0000000000"), and then cutting it off from the second index (3rd character) with a length of eight characters. For the rest of the cases, the addition of zeros will not harm the result because it is cutting it off anyway.
  • Math.random().toString(16)+"000000000").substr(2,8).

The assembly:

  • The GUID is in the following format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • I divided the GUID into 4 pieces, each piece divided into 2 types (or formats): XXXXXXXX and -XXXX-XXXX.
  • Now I’m building the GUID using these 2 types to assemble the GUID with call 4 pieces, as follows: XXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX.
  • To differ between these two types, I added a flag parameter to a pair creator function _p8(s), the s parameter tells the function whether to add dashes or not.
  • Eventually we build the GUID with the following chaining: _p8() + _p8(true) + _p8(true) + _p8(), and return it.

Enjoy! 🙂

9 comments

1. These are not valid RFC4122 IDs. (Making them valid is fairly trivial – just make sure the ‘variant’ and version’ fields are set properly.)
2. “Million executions of this implementation takes just 32.5 seconds” is a largely meaningless statement without a description of the JS execution environment you’re running this code in.
2a. … and my experience (with the node-uuid project) is that UUID generation performance isn’t a significant concern. I suspect this is because the work required to generate a UUID is insignificant compared to work being done by the calling code (e.g. creating new data structures, updating UI, issuing network requests, persisting state to a data store, etc.)

Just my $.02.

1. It is not RFC4122 compliance, but a random ID that looks like GUID.
2. I tested it on WebKit engine. You are welcome to test it yourself wherever you like, that’s why I published a test case.
2a. In my case, I generated several thousands of these at once, so for me performance was important.

Collisions may occur as it uses `Math.random`, but the probability is almost zero, as in case of collision the same four exactly random numbers should appear in the exact order.
I have tested this script to generate billions of UUIDs and never got a single collision.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.