From 0ee0b67c37846529c66089880414d29f3ae132d5 Mon Sep 17 00:00:00 2001 From: Ignat Prokopovich Date: Mon, 25 May 2020 22:39:11 +0300 Subject: [PATCH] feat: improve performance of v1 string representation (#453) Pre-allocate a fixed size array instead of an empty array when no array is passed. --- examples/benchmark/benchmark.js | 8 ++++++- src/bytesToUuid.js | 38 +++++++++++++++------------------ src/v1.js | 4 +++- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/examples/benchmark/benchmark.js b/examples/benchmark/benchmark.js index b62b16ae..dc3ff19f 100644 --- a/examples/benchmark/benchmark.js +++ b/examples/benchmark/benchmark.js @@ -21,7 +21,13 @@ suite uuidv1(); }) .add('uuidv1() fill existing array', function () { - uuidv1(null, array, 0); + try { + uuidv1(null, array, 0); + } catch (err) { + // The spec (https://tools.ietf.org/html/rfc4122#section-4.2.1.2) defines that only 10M/s v1 + // UUIDs can be generated on a single node. This library throws an error if we hit that limit + // (which can happen on modern hardware and modern Node.js versions). + } }) .add('uuidv4()', function () { uuidv4(); diff --git a/src/bytesToUuid.js b/src/bytesToUuid.js index 7e90bdb9..0c27824b 100644 --- a/src/bytesToUuid.js +++ b/src/bytesToUuid.js @@ -8,34 +8,30 @@ for (let i = 0; i < 256; ++i) { byteToHex.push((i + 0x100).toString(16).substr(1)); } -function bytesToUuid(buf, offset) { - const i = offset || 0; - - const bth = byteToHex; - +function bytesToUuid(buf, offset = 0) { // Note: Be careful editing this code! It's been tuned for performance // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 return ( - bth[buf[i + 0]] + - bth[buf[i + 1]] + - bth[buf[i + 2]] + - bth[buf[i + 3]] + + byteToHex[buf[offset + 0]] + + byteToHex[buf[offset + 1]] + + byteToHex[buf[offset + 2]] + + byteToHex[buf[offset + 3]] + '-' + - bth[buf[i + 4]] + - bth[buf[i + 5]] + + byteToHex[buf[offset + 4]] + + byteToHex[buf[offset + 5]] + '-' + - bth[buf[i + 6]] + - bth[buf[i + 7]] + + byteToHex[buf[offset + 6]] + + byteToHex[buf[offset + 7]] + '-' + - bth[buf[i + 8]] + - bth[buf[i + 9]] + + byteToHex[buf[offset + 8]] + + byteToHex[buf[offset + 9]] + '-' + - bth[buf[i + 10]] + - bth[buf[i + 11]] + - bth[buf[i + 12]] + - bth[buf[i + 13]] + - bth[buf[i + 14]] + - bth[buf[i + 15]] + byteToHex[buf[offset + 10]] + + byteToHex[buf[offset + 11]] + + byteToHex[buf[offset + 12]] + + byteToHex[buf[offset + 13]] + + byteToHex[buf[offset + 14]] + + byteToHex[buf[offset + 15]] ).toLowerCase(); } diff --git a/src/v1.js b/src/v1.js index 52a49f54..dbf4f5ca 100644 --- a/src/v1.js +++ b/src/v1.js @@ -16,7 +16,7 @@ let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details function v1(options, buf, offset) { let i = (buf && offset) || 0; - const b = buf || []; + const b = buf || new Array(16); options = options || {}; let node = options.node || _nodeId; @@ -27,6 +27,7 @@ function v1(options, buf, offset) { // system entropy. See #189 if (node == null || clockseq == null) { const seedBytes = options.random || (options.rng || rng)(); + if (node == null) { // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) node = _nodeId = [ @@ -38,6 +39,7 @@ function v1(options, buf, offset) { seedBytes[5], ]; } + if (clockseq == null) { // Per 4.2.2, randomize (14 bit) clockseq clockseq = _clockseq = ((seedBytes[6] << 8) | seedBytes[7]) & 0x3fff;