uuidv4() comparison

Benchmark created on


Setup

const HEX = new Array(256);
for (let i = 0; i < 256; i++) {
    HEX[i] = (i < 16 ? '0' : '') + i.toString(16);
}

	function uuidv4_1() {
		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
			var r = Math.random() * 16 | 0;
			var v = c == 'x' ? r : (r & 0x3 | 0x8);
			return v.toString(16);
		});
	}

function uuidv4_2() {
    // Pull 16 random bytes using Math.random()
    // 4 bytes per call = 4 RNG calls total
    let r0 = Math.random() * 0x100000000 >>> 0;
    let r1 = Math.random() * 0x100000000 >>> 0;
    let r2 = Math.random() * 0x100000000 >>> 0;
    let r3 = Math.random() * 0x100000000 >>> 0;

    // Extract bytes
    let b0  =  r0        & 0xff;
    let b1  = (r0 >>>  8) & 0xff;
    let b2  = (r0 >>> 16) & 0xff;
    let b3  = (r0 >>> 24) & 0xff;

    let b4  =  r1        & 0xff;
    let b5  = (r1 >>>  8) & 0xff;
    let b6  = (r1 >>> 16) & 0xff;
    let b7  = (r1 >>> 24) & 0xff;

    let b8  =  r2        & 0xff;
    let b9  = (r2 >>>  8) & 0xff;
    let b10 = (r2 >>> 16) & 0xff;
    let b11 = (r2 >>> 24) & 0xff;

    let b12 =  r3        & 0xff;
    let b13 = (r3 >>>  8) & 0xff;
    let b14 = (r3 >>> 16) & 0xff;
    let b15 = (r3 >>> 24) & 0xff;

    // RFC 4122 fixes
    b6 = (b6 & 0x0f) | 0x40; // version 4
    b8 = (b8 & 0x3f) | 0x80; // variant 10xx

    // Manual string construction (no loops, no joins)
    return (
        HEX[b0]  + HEX[b1]  + HEX[b2]  + HEX[b3]  + '-' +
        HEX[b4]  + HEX[b5]  + '-' +
        HEX[b6]  + HEX[b7]  + '-' +
        HEX[b8]  + HEX[b9]  + '-' +
        HEX[b10] + HEX[b11] + HEX[b12] +
        HEX[b13] + HEX[b14] + HEX[b15]
    );
}

	var s0 = (Date.now() ^ (performance.now() * 1e6)) >>> 0;
	var s1 = ((Math.random() * 0x100000000) >>> 0) ^ 0xdeadbeef;
	// PRNG function for fast (NOT SECURE) 32-bit random numbers
	// xoroshiro128+
	function next32() {
		var x = s0;
		var y = s1;
		s0 = y;
		x ^= x << 23;
		s1 = x ^ y ^ (x >>> 17) ^ (y >>> 26);

		return (s1 + y) >>> 0;
	}

	function uuidv4_3() {
		// Pull 16 bytes from 4 PRNG calls
		var r0 = next32();
		var r1 = next32();
		var r2 = next32();
		var r3 = next32();

		// Extract bytes
		var b00 =  r0         & 0xff;
		var b01 = (r0 >>>  8) & 0xff;
		var b02 = (r0 >>> 16) & 0xff;
		var b03 = (r0 >>> 24) & 0xff;

		var b04 =  r1         & 0xff;
		var b05 = (r1 >>>  8) & 0xff;
		var b06 = (r1 >>> 16) & 0xff;
		var b07 = (r1 >>> 24) & 0xff;

		var b08 =  r2         & 0xff;
		var b09 = (r2 >>>  8) & 0xff;
		var b10 = (r2 >>> 16) & 0xff;
		var b11 = (r2 >>> 24) & 0xff;

		var b12 =  r3         & 0xff;
		var b13 = (r3 >>>  8) & 0xff;
		var b14 = (r3 >>> 16) & 0xff;
		var b15 = (r3 >>> 24) & 0xff;

		// RFC 4122 fixes
		b06 = (b06 & 0x0f) | 0x40; // version 4
		b08 = (b08 & 0x3f) | 0x80; // variant 10xx

		return (
			        HEX[b00] + HEX[b01] + HEX[b02] + HEX[b03]
			+ '-' + HEX[b04] + HEX[b05]
			+ '-' + HEX[b06] + HEX[b07]
			+ '-' + HEX[b08] + HEX[b09]
			+ '-' + HEX[b10] + HEX[b11] + HEX[b12] + HEX[b13] + HEX[b14] + HEX[b15]
		);
	}
	
	function uuidv4_4() {
		const
			  r0 = next32()
			, r1 = next32()
			, r2 = next32()
			, r3 = next32()
		;
		return (
			        HEX[  r0         & 0xff]         + HEX[(r0 >>>  8) & 0xff]
			      + HEX[ (r0 >>> 16) & 0xff]         + HEX[(r0 >>> 24) & 0xff]
			+ '-' + HEX[  r1         & 0xff]         + HEX[(r1 >>>  8) & 0xff]
			+ '-' + HEX[((r1 >>> 16) & 0x0f) | 0x40] + HEX[(r1 >>> 24) & 0xff]
			+ '-' + HEX[ (r2         & 0x3f) | 0x80] + HEX[(r2 >>>  8) & 0xff]
			+ '-' + HEX[ (r2 >>> 16) & 0xff]         + HEX[(r2 >>> 24) & 0xff]
			      + HEX[  r3         & 0xff]         + HEX[(r3 >>>  8) & 0xff]
				  + HEX[ (r3 >>> 16) & 0xff]         + HEX[(r3 >>> 24) & 0xff]
		);
	}
	
	function uuidv4_5() {
		const
			  r0 = Math.random() * 0x100000000 >>> 0
			, r1 = Math.random() * 0x100000000 >>> 0
			, r2 = Math.random() * 0x100000000 >>> 0
			, r3 = Math.random() * 0x100000000 >>> 0
		;
		return (
			        HEX[  r0         & 0xff]         + HEX[(r0 >>>  8) & 0xff]
			      + HEX[ (r0 >>> 16) & 0xff]         + HEX[(r0 >>> 24) & 0xff]
			+ '-' + HEX[  r1         & 0xff]         + HEX[(r1 >>>  8) & 0xff]
			+ '-' + HEX[((r1 >>> 16) & 0x0f) | 0x40] + HEX[(r1 >>> 24) & 0xff]
			+ '-' + HEX[ (r2         & 0x3f) | 0x80] + HEX[(r2 >>>  8) & 0xff]
			+ '-' + HEX[ (r2 >>> 16) & 0xff]         + HEX[(r2 >>> 24) & 0xff]
			      + HEX[  r3         & 0xff]         + HEX[(r3 >>>  8) & 0xff]
				  + HEX[ (r3 >>> 16) & 0xff]         + HEX[(r3 >>> 24) & 0xff]
		);
	}
	
function uuidv4_6() {
    const buf = new Uint8Array(16);
    crypto.getRandomValues(buf);
    buf[6] = (buf[6] & 0x0f) | 0x40; // version
    buf[8] = (buf[8] & 0x3f) | 0x80; // variant
    return (
        HEX[buf[0]] + HEX[buf[1]] + HEX[buf[2]] + HEX[buf[3]] + '-' +
        HEX[buf[4]] + HEX[buf[5]] + '-' +
        HEX[buf[6]] + HEX[buf[7]] + '-' +
        HEX[buf[8]] + HEX[buf[9]] + '-' +
        HEX[buf[10]] + HEX[buf[11]] + HEX[buf[12]] + HEX[buf[13]] + HEX[buf[14]] + HEX[buf[15]]
    );
}

	var s0 = (Date.now() ^ (performance.now() * 1e6)) >>> 0;
	var s1 = ((Math.random() * 0x100000000) >>> 0) ^ 0xdeadbeef;
	// PRNG function for fast (NOT SECURE) 32-bit random numbers
	// xoroshiro128+
	function next32() {
		var x = s0;
		var y = s1;
		s0 = y;
		x ^= x << 23;
		s1 = x ^ y ^ (x >>> 17) ^ (y >>> 26);

		return (s1 + y) >>> 0;
	}

Test runner

Ready to run.

Testing in
TestOps/sec
uuidv4_1
var id = uuidv4_1();
ready
uuidv4_2
var id = uuidv4_2();
ready
uuidv4_3
var id = uuidv4_3();
ready
uuidv4_4
var id = uuidv4_4();
ready
uuidv4_5
var id = uuidv4_5();
ready
uuidv4_6
var id = uuidv4_6();
ready
crypto.randomUUID
var id = crypto.randomUUID();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.