uuid-random
Advanced tools
Comparing version 1.0.9 to 1.3.0
@@ -7,17 +7,26 @@ /* | ||
npm install an-uiid node-uuid portable-uuid pure-uuid simply-uuid uuid uuid-v4 | ||
npm i uuid-random id128 portable-uuid uuid | ||
*/ | ||
var id128 = require('id128'); | ||
var uuids = { | ||
// Keeping up with competition | ||
'an-uuid': require('an-uuid'), | ||
// This is the "best" one | ||
'node-uuid': require('node-uuid'), | ||
// This lib (fastest) | ||
'uuid-random': require('./index'), | ||
// This doesn't even work? | ||
// Really extensive uuid lib | ||
'id128': () => id128.Uuid4.generate().toCanonical(), | ||
// No longer exists? | ||
// 'an-uuid': require('an-uuid'), | ||
// Deprecated. | ||
// 'node-uuid': require('node-uuid'), | ||
// Doesn't even work anymore? | ||
// 'performance-uuid': require('performance-uuid').uuid, | ||
// Slightly slower | ||
// Slightly slower. | ||
'portable-uuid': require('portable-uuid'), | ||
@@ -28,12 +37,12 @@ | ||
// 'simply-uuid': require('simply-uuid').generate, | ||
// Best npm package name | ||
'uuid': require('uuid'), | ||
'uuid': require('uuid').v4, | ||
// This lib (fastest) | ||
'uuid-random': require('./index') | ||
// 2nd best npm package name | ||
// Uses Math.random() | ||
// 'fast-uuid': require('fast-uuid').uuid4, | ||
}; | ||
var i, start, seconds, ops = 1000000; | ||
@@ -47,44 +56,1 @@ | ||
} | ||
*/ | ||
// global | ||
var i, start, seconds, ops = 5000000; | ||
// Test ours here | ||
var uuid_random = require('./index'); | ||
start = + new Date; | ||
for (i = 0; i < ops; i++) uuid_random(); | ||
seconds = ((+new Date) - start) / 1000; | ||
console.log('uuid-random', (ops/seconds) + " ops/sec"); | ||
start = + new Date; | ||
for (i = 0; i < ops; i++) uuid_random.bin(); | ||
seconds = ((+new Date) - start) / 1000; | ||
console.log('uuid-random-bin', (ops/seconds) + " ops/sec"); | ||
var snowflake = require('./snowflake'); | ||
start = + new Date; | ||
for (i = 0; i < ops; i++) snowflake(); | ||
seconds = ((+new Date) - start) / 1000; | ||
console.log('snowflake', (ops/seconds) + " ops/sec"); | ||
// simpleflakes | ||
var simpleflakes = require('simpleflakes'); | ||
start = + new Date; | ||
for (i = 0; i < ops; i++) simpleflakes.simpleflake(); | ||
seconds = ((+new Date) - start) / 1000; | ||
console.log('simpleflakes', (ops/seconds) + " ops/sec"); | ||
// simpleflake (slow as dick) | ||
// var simpleflake = require('simpleflake'); | ||
// start = + new Date; | ||
// for (i = 0; i < ops; i++) simpleflake(); | ||
// seconds = ((+new Date) - start) / 1000; | ||
// console.log('simpleflake', (ops/seconds) + " ops/sec"); | ||
// node-uuid | ||
// var node_uuid = require('node-uuid'); | ||
// start = + new Date; | ||
// for (i = 0; i < ops; i++) node_uuid(); | ||
// seconds = ((+new Date) - start) / 1000; | ||
// console.log('node-uuid', (ops/seconds) + " ops/sec"); |
118
index.js
@@ -5,3 +5,3 @@ "use strict"; | ||
var | ||
var | ||
buf, | ||
@@ -13,31 +13,39 @@ bufIdx = 0, | ||
// Improve memory performance by decreasing this number (>=16) | ||
// Pre-calculate toString(16) for speed | ||
for (i = 0; i < 256; i++) { | ||
hexBytes[i] = (i + 0x100).toString(16).substr(1); | ||
} | ||
// Buffer random numbers for speed | ||
// Reduce memory usage by decreasing this number (min 16) | ||
// or improve speed by increasing this number (try 16384) | ||
uuid.BUFFER_SIZE = 512; | ||
uuid.BUFFER_SIZE = 4096; | ||
// Binary uuids (even faster) | ||
uuid.bin = uuidbin; | ||
// Binary uuids | ||
uuid.bin = uuidBin; | ||
// Clear buffer | ||
uuid.clearBuffer = function() { | ||
buf = null; | ||
bufIdx = 0; | ||
}; | ||
// Test for uuid | ||
uuid.test = isUUID; | ||
uuid.test = function(uuid) { | ||
if (typeof uuid === 'string') { | ||
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(uuid); | ||
} | ||
return false; | ||
}; | ||
// Cache toString(16) | ||
// This is massively impactful on performance | ||
for (i = 0; i < 256; i++) { | ||
// This is a fast way to ensure a 2 char hex byte | ||
hexBytes[i] = (i + 0x100).toString(16).substr(1); | ||
} | ||
// Node & Browser support | ||
var _crypto; | ||
if(typeof crypto !== 'undefined') { | ||
_crypto = crypto; | ||
var crypt0; | ||
if (typeof crypto !== 'undefined') { | ||
crypt0 = crypto; | ||
} else if( (typeof window !== 'undefined') && (typeof window.msCrypto !== 'undefined')) { | ||
// IE11 | ||
_crypto = window.msCrypto; | ||
} | ||
crypt0 = window.msCrypto; // IE11 | ||
} | ||
if ((typeof module !== 'undefined') && (typeof require === 'function')) { | ||
_crypto = _crypto || require('crypto'); | ||
crypt0 = crypt0 || require('crypto'); | ||
module.exports = uuid; | ||
@@ -48,42 +56,38 @@ } else if (typeof window !== 'undefined') { | ||
// Backup method | ||
function getRandomInt(min, max) { | ||
return Math.floor(Math.random() * (max - min)) + min; | ||
} | ||
// uuid.test | ||
function isUUID(uuid) { | ||
if (typeof uuid === 'string') { | ||
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(uuid); | ||
// Use best available PRNG | ||
// Also expose this so you can override it. | ||
uuid.randomBytes = (function(){ | ||
if (crypt0) { | ||
if (crypt0.randomBytes) { | ||
return crypt0.randomBytes; | ||
} | ||
if (crypt0.getRandomValues) { | ||
return function(n) { | ||
var bytes = new Uint8Array(n); | ||
crypt0.getRandomValues(bytes); | ||
return bytes; | ||
}; | ||
} | ||
} | ||
} | ||
// Use best RNG as possible | ||
function randomBytes(n) { | ||
var r; | ||
if (typeof _crypto !== 'undefined') { | ||
if ((typeof buf === 'undefined') || ((bufIdx + n) > uuid.BUFFER_SIZE)) { | ||
bufIdx = 0; | ||
if (_crypto.getRandomValues) { | ||
buf = new Uint8Array(uuid.BUFFER_SIZE); | ||
_crypto.getRandomValues(buf); | ||
} else if (_crypto.randomBytes) { | ||
buf = _crypto.randomBytes(uuid.BUFFER_SIZE); | ||
} else { | ||
throw new Error('Non-standard crypto library'); | ||
} | ||
} | ||
return buf.slice(bufIdx, bufIdx += n); | ||
} else { | ||
r = []; | ||
return function(n) { | ||
var i, r = []; | ||
for (i = 0; i < n; i++) { | ||
r.push(getRandomInt(0, 255)); | ||
r.push(Math.floor(Math.random() * 256)); | ||
} | ||
return r; | ||
}; | ||
})(); | ||
// Buffer some random bytes for speed | ||
function randomBytesBuffered(n) { | ||
if (!buf || ((bufIdx + n) > uuid.BUFFER_SIZE)) { | ||
bufIdx = 0; | ||
buf = uuid.randomBytes(uuid.BUFFER_SIZE); | ||
} | ||
return buf.slice(bufIdx, bufIdx += n); | ||
} | ||
// uuid.bin | ||
function uuidbin() { | ||
var b = randomBytes(16); | ||
function uuidBin() { | ||
var b = randomBytesBuffered(16); | ||
b[6] = (b[6] & 0x0f) | 0x40; | ||
@@ -96,4 +100,4 @@ b[8] = (b[8] & 0x3f) | 0x80; | ||
function uuid() { | ||
var b = uuidbin(); | ||
return hexBytes[b[0]] + hexBytes[b[1]] + | ||
var b = uuidBin(); | ||
return hexBytes[b[0]] + hexBytes[b[1]] + | ||
hexBytes[b[2]] + hexBytes[b[3]] + '-' + | ||
@@ -103,3 +107,3 @@ hexBytes[b[4]] + hexBytes[b[5]] + '-' + | ||
hexBytes[b[8]] + hexBytes[b[9]] + '-' + | ||
hexBytes[b[10]] + hexBytes[b[11]] + | ||
hexBytes[b[10]] + hexBytes[b[11]] + | ||
hexBytes[b[12]] + hexBytes[b[13]] + | ||
@@ -110,2 +114,2 @@ hexBytes[b[14]] + hexBytes[b[15]] | ||
})(); | ||
})(); |
{ | ||
"name": "uuid-random", | ||
"version": "1.0.9", | ||
"version": "1.3.0", | ||
"description": "Fastest UUIDv4 with good RNG", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
# uuid-random | ||
Generate RFC-4122 compliant | ||
[random UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29) | ||
with better | ||
[statistical dispersion](https://en.wikipedia.org/wiki/Statistical_dispersion) | ||
than `Math.random()`. | ||
[![MIT Licence](https://img.shields.io/badge/License-MIT-informational)](LICENSE.txt) | ||
[![Stable](https://img.shields.io/badge/Stable-1.3.0-brightgreen)](https://github.com/jchook/uuid-random/releases) | ||
Generate RFC-4122 compliant [random UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29) (version 4) with better [statistical dispersion](https://en.wikipedia.org/wiki/Statistical_dispersion) than `Math.random()`. | ||
## Install | ||
npm install uuid-random | ||
```sh | ||
npm i uuid-random | ||
``` | ||
Or download the [latest release](https://github.com/jchook/uuid-random/releases). | ||
## Features | ||
* 0.3k minified + gzipped | ||
* Uses [better RNG](http://caniuse.com/#feat=getrandomvalues) when possible | ||
* Works in browser or node with zero external dependencies | ||
* Tiny (0.6k minified + gzipped) | ||
* Uses [cryptographic randomness](http://caniuse.com/#feat=getrandomvalues) when possible | ||
* Very fast! | ||
## Compatability | ||
Compatible with almost all versions of: | ||
- Node | ||
- Babel | ||
- TypeScript | ||
- Web browsers | ||
## Performance | ||
This is the fastest pure javascript UUID v4 generator I have found, | ||
over **5x faster** than comparable libraries. After inspecting and/or testing every JS UUID package I could find (there are a ton), these were the fastest: | ||
The included `benchmark.js` as well as [independent benchmarks](https://github.com/aarondcohen/benchmark-guid) rank this library as the _fastest_ pure JS UUID v4 generator available with cryptographically secure PRNG— almost **5x faster** than the most popular library. | ||
| npm package | performance | | ||
|-----------------|-----------------| | ||
| node-uuid | 370k ops/sec | | ||
| portable-uuid | 260k ops/sec | | ||
| uuid | 370k ops/sec | | ||
| **uuid-random** | **2M ops/sec** | | ||
| portable-uuid | 487k ops/sec | | ||
| uuid | 502k ops/sec | | ||
| id128 | 2.1M ops/sec | | ||
| **uuid-random** <small>(this)</small> | **2.7M ops/sec** | | ||
*Results above generated on a 4.20GHz Intel i7-7700K with Node 10.15.0* | ||
## What is UUID v4? | ||
## Why use UUID? | ||
**U**niversally **U**nique **ID**entifiers transcend many constraints of | ||
traditional incremental integer IDs, especially in distributed systems. With | ||
version 4, we (essentially) generate a random 128-bit value. | ||
**U**niversally **U**nique **ID**entifiers transcend many constraints of traditional incremental integer IDs, especially in distributed systems. In UUID version 4, we essentially generate a random 128-bit value. | ||
We do sacrifice guaranteed uniqueness for __extremely__ probable uniqueness (you | ||
would need to do-loop `uuid()` at max speed for 73,067 years for a 50% chance of | ||
**one** collision). But for that slight cost, we may now generate valid, unique, | ||
persistent IDs on any node of a distributed system (e.g. intermittently offline | ||
or high-latency clients). | ||
We do trade guaranteed uniqueness for __extremely__ probable uniqueness (you would need to do-loop `uuid()` at max speed for 73,067 years for a 50% chance of **one** collision). But for that slight cost, we may now generate valid, unique, persistent IDs on any node of a distributed system (e.g. intermittently offline or high-latency clients). | ||
_Note, if you plan to use UUIDs for a new project, depending on your requirements, you may consider a more recent standard that addresses some of the shortcomings of UUID, such as [flake-id](https://github.com/T-PWK/flake-idgen), [nanoid](https://github.com/ai/nanoid), [cuid](https://github.com/ericelliott/cuid), or [ulid](https://github.com/ulid/spec)._ | ||
## Example Usage | ||
@@ -74,3 +81,3 @@ | ||
### Is UUID? | ||
### Validate a UUID v4 String | ||
@@ -81,24 +88,15 @@ ```javascript | ||
## Rationale | ||
### Generate Binary UUIDs | ||
Random (v4) UUIDs are often | ||
[better](https://blogs.msdn.microsoft.com/oldnewthing/20160114-00/?p=92851) than | ||
clock-based (v1), but `Math.random()` | ||
[sucks](https://medium.com/@betable/tifu-by-using-math-random-f1c308c4fd9d) | ||
[for](http://devoluk.com/google-chrome-math-random-issue.html) | ||
[uuid generation](http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript). | ||
```javascript | ||
uuid.bin(); // <Buffer 41 db 10 54 b3 61 48 50 87 f1 2f 7b 08 a5 0f 06> | ||
``` | ||
After digging through [npm](https://www.npmjs.com/search?q=uuid) | ||
I settled on using [node-uuid](https://github.com/broofa/node-uuid) to take | ||
advantage of better RNG when possible. It's a great lib, but seemed too large | ||
and featured after using that neat [oneliner-ish solution](http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript/2117523#2117523). | ||
So, I combined ideas from the better implementations and | ||
[researched](https://gist.github.com/jed/982883) a *much* faster, more focused | ||
and compact uuid generator that used the best RNG available. | ||
This library does one thing very well: generate UUID version 4. | ||
## Contributing | ||
Feel free to [open an issue](https://github.com/jchook/uuid-random/issues) or submit a [pull request](https://github.com/jchook/uuid-random/pulls). | ||
## License | ||
MIT | ||
MIT. |
16
test.js
@@ -0,7 +1,15 @@ | ||
var assert = require('assert'); | ||
var uuid = require('./index'); | ||
// Check format | ||
var i; | ||
for (i = 0; i<1000000; i++) { | ||
if (! | ||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(uuid()) | ||
) throw new Exception('Invalid UUID'); | ||
for (i = 0; i<10000; i++) { | ||
assert(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(uuid())); | ||
} | ||
// Clear the buffer and change the randomBytes function to return 0s | ||
uuid.clearBuffer(); | ||
uuid.randomBytes = function(length) { | ||
return (new Array(length)).fill(0, 0, length); | ||
}; | ||
assert(uuid() === '00000000-0000-4000-8000-000000000000'); |
@@ -1,1 +0,1 @@ | ||
"use strict";!function(){var r,n,t,o=0,e=[];for(f.BUFFER_SIZE=512,f.bin=i,f.test=function(r){if("string"==typeof r)return/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(r)},n=0;n<256;n++)e[n]=(n+256).toString(16).substr(1);function i(){var e=function(e){var i,d,u;if(void 0!==t){if(void 0===r||o+e>f.BUFFER_SIZE)if(o=0,t.getRandomValues)r=new Uint8Array(f.BUFFER_SIZE),t.getRandomValues(r);else{if(!t.randomBytes)throw new Error("Non-standard crypto library");r=t.randomBytes(f.BUFFER_SIZE)}return r.slice(o,o+=e)}for(i=[],n=0;n<e;n++)i.push((d=0,u=255,Math.floor(Math.random()*(u-d))+d));return i}(16);return e[6]=15&e[6]|64,e[8]=63&e[8]|128,e}function f(){var r=i();return e[r[0]]+e[r[1]]+e[r[2]]+e[r[3]]+"-"+e[r[4]]+e[r[5]]+"-"+e[r[6]]+e[r[7]]+"-"+e[r[8]]+e[r[9]]+"-"+e[r[10]]+e[r[11]]+e[r[12]]+e[r[13]]+e[r[14]]+e[r[15]]}"undefined"!=typeof crypto?t=crypto:"undefined"!=typeof window&&void 0!==window.msCrypto&&(t=window.msCrypto),"undefined"!=typeof module&&"function"==typeof require?(t=t||require("crypto"),module.exports=f):"undefined"!=typeof window&&(window.uuid=f)}(); | ||
"use strict";!function(){var n,t,r,e=0,o=[];for(t=0;t<256;t++)o[t]=(t+256).toString(16).substr(1);function u(){var t,r=(t=16,(!n||e+t>f.BUFFER_SIZE)&&(e=0,n=f.randomBytes(f.BUFFER_SIZE)),n.slice(e,e+=t));return r[6]=15&r[6]|64,r[8]=63&r[8]|128,r}function f(){var n=u();return o[n[0]]+o[n[1]]+o[n[2]]+o[n[3]]+"-"+o[n[4]]+o[n[5]]+"-"+o[n[6]]+o[n[7]]+"-"+o[n[8]]+o[n[9]]+"-"+o[n[10]]+o[n[11]]+o[n[12]]+o[n[13]]+o[n[14]]+o[n[15]]}f.BUFFER_SIZE=4096,f.bin=u,f.clearBuffer=function(){n=null,e=0},f.test=function(n){return"string"==typeof n&&/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(n)},"undefined"!=typeof crypto?r=crypto:"undefined"!=typeof window&&void 0!==window.msCrypto&&(r=window.msCrypto),"undefined"!=typeof module&&"function"==typeof require?(r=r||require("crypto"),module.exports=f):"undefined"!=typeof window&&(window.uuid=f),f.randomBytes=function(){if(r){if(r.randomBytes)return r.randomBytes;if(r.getRandomValues)return function(n){var t=new Uint8Array(n);return r.getRandomValues(t),t}}return function(n){var t,r=[];for(t=0;t<n;t++)r.push(Math.floor(256*Math.random()));return r}}()}(); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14798
13
176
101
1