Why is webAssembly function almost 300 time slower than same JS function - javascript

Find length of line 300* slower
First of I have read the answer to Why is my WebAssembly function slower than the JavaScript equivalent?
But it has shed little light on the problem, and I have invested a lot of time that may well be that yellow stuff against the wall.
I do not use globals, I do not use any memory. I have two simple functions that find the length of a line segment and compare them to the same thing in plain old Javascript. I have 4 params 3 more locals and returns a float or double.
On Chrome the Javascript is 40 times faster than the webAssembly and on firefox the wasm is almost 300 times slower than the Javascript.
jsPref test case.
I have added a test case to jsPref WebAssembly V Javascript math
What am I doing wrong?
Either
I have missed an obvious bug, bad practice, or I am suffering coder stupidity.
WebAssembly is not for 32bit OS (win 10 laptop i7CPU)
WebAssembly is far from a ready technology.
Please please be option 1.
I have read the webAssembly use case
Re-use existing code by targeting WebAssembly, embedded in a larger
JavaScript / HTML application. This could be anything from simple
helper libraries, to compute-oriented task offload.
I was hoping I could replace some geometry libs with webAssembly to get some extra performance. I was hoping that it would be awesome, like 10 or more times faster. BUT 300 times slower WTF.
UPDATE
This is not a JS optimisation issues.
To ensure that optimisation has as little as possible effect I have tested using the following methods to reduce or eliminate any optimisation bias..
counter c += length(... to ensure all code is executed.
bigCount += c to ensure whole function is executed. Not needed
4 lines for each function to reduce a inlining skew. Not Needed
all values are randomly generated doubles
each function call returns a different result.
add slower length calculation in JS using Math.hypot to prove code is being run.
added empty call that return first param JS to see overhead
// setup and associated functions
const setOf = (count, callback) => {var a = [],i = 0; while (i < count) { a.push(callback(i ++)) } return a };
const rand = (min = 1, max = min + (min = 0)) => Math.random() * (max - min) + min;
const a = setOf(100009,i=>rand(-100000,100000));
var bigCount = 0;
function len(x,y,x1,y1){
var nx = x1 - x;
var ny = y1 - y;
return Math.sqrt(nx * nx + ny * ny);
}
function lenSlow(x,y,x1,y1){
var nx = x1 - x;
var ny = y1 - y;
return Math.hypot(nx,ny);
}
function lenEmpty(x,y,x1,y1){
return x;
}
// Test functions in same scope as above. None is in global scope
// Each function is copied 4 time and tests are performed randomly.
// c += length(... to ensure all code is executed.
// bigCount += c to ensure whole function is executed.
// 4 lines for each function to reduce a inlining skew
// all values are randomly generated doubles
// each function call returns a different result.
tests : [{
func : function (){
var i,c=0,a1,a2,a3,a4;
for (i = 0; i < 10000; i += 1) {
a1 = a[i];
a2 = a[i+1];
a3 = a[i+2];
a4 = a[i+3];
c += length(a1,a2,a3,a4);
c += length(a2,a3,a4,a1);
c += length(a3,a4,a1,a2);
c += length(a4,a1,a2,a3);
}
bigCount = (bigCount + c) % 1000;
},
name : "length64",
},{
func : function (){
var i,c=0,a1,a2,a3,a4;
for (i = 0; i < 10000; i += 1) {
a1 = a[i];
a2 = a[i+1];
a3 = a[i+2];
a4 = a[i+3];
c += lengthF(a1,a2,a3,a4);
c += lengthF(a2,a3,a4,a1);
c += lengthF(a3,a4,a1,a2);
c += lengthF(a4,a1,a2,a3);
}
bigCount = (bigCount + c) % 1000;
},
name : "length32",
},{
func : function (){
var i,c=0,a1,a2,a3,a4;
for (i = 0; i < 10000; i += 1) {
a1 = a[i];
a2 = a[i+1];
a3 = a[i+2];
a4 = a[i+3];
c += len(a1,a2,a3,a4);
c += len(a2,a3,a4,a1);
c += len(a3,a4,a1,a2);
c += len(a4,a1,a2,a3);
}
bigCount = (bigCount + c) % 1000;
},
name : "length JS",
},{
func : function (){
var i,c=0,a1,a2,a3,a4;
for (i = 0; i < 10000; i += 1) {
a1 = a[i];
a2 = a[i+1];
a3 = a[i+2];
a4 = a[i+3];
c += lenSlow(a1,a2,a3,a4);
c += lenSlow(a2,a3,a4,a1);
c += lenSlow(a3,a4,a1,a2);
c += lenSlow(a4,a1,a2,a3);
}
bigCount = (bigCount + c) % 1000;
},
name : "Length JS Slow",
},{
func : function (){
var i,c=0,a1,a2,a3,a4;
for (i = 0; i < 10000; i += 1) {
a1 = a[i];
a2 = a[i+1];
a3 = a[i+2];
a4 = a[i+3];
c += lenEmpty(a1,a2,a3,a4);
c += lenEmpty(a2,a3,a4,a1);
c += lenEmpty(a3,a4,a1,a2);
c += lenEmpty(a4,a1,a2,a3);
}
bigCount = (bigCount + c) % 1000;
},
name : "Empty",
}
],
Results from update.
Because there is a lot more overhead in the test the results are closer but the JS code is still two orders of magnitude faster.
Note how slow the function Math.hypot is. If optimisation was in effect that function would be near the faster len function.
WebAssembly 13389µs
Javascript 728µs
/*
=======================================
Performance test. : WebAssm V Javascript
Use strict....... : true
Data view........ : false
Duplicates....... : 4
Cycles........... : 147
Samples per cycle : 100
Tests per Sample. : undefined
---------------------------------------------
Test : 'length64'
Mean : 12736µs ±69µs (*) 3013 samples
---------------------------------------------
Test : 'length32'
Mean : 13389µs ±94µs (*) 2914 samples
---------------------------------------------
Test : 'length JS'
Mean : 728µs ±6µs (*) 2906 samples
---------------------------------------------
Test : 'Length JS Slow'
Mean : 23374µs ±191µs (*) 2939 samples << This function use Math.hypot
rather than Math.sqrt
---------------------------------------------
Test : 'Empty'
Mean : 79µs ±2µs (*) 2928 samples
-All ----------------------------------------
Mean : 10.097ms Totals time : 148431.200ms 14700 samples
(*) Error rate approximation does not represent the variance.
*/
Whats the point of WebAssambly if it does not optimise
End of update
All the stuff related to the problem.
Find length of a line.
Original source in custom language
// declare func the < indicates export name, the param with types and return type
func <lengthF(float x, float y, float x1, float y1) float {
float nx, ny, dist; // declare locals float is f32
nx = x1 - x;
ny = y1 - y;
dist = sqrt(ny * ny + nx * nx);
return dist;
}
// and as double
func <length(double x, double y, double x1, double y1) double {
double nx, ny, dist;
nx = x1 - x;
ny = y1 - y;
dist = sqrt(ny * ny + nx * nx);
return dist;
}
Code compiles to Wat for proof read
(module
(func
(export "lengthF")
(param f32 f32 f32 f32)
(result f32)
(local f32 f32 f32)
get_local 2
get_local 0
f32.sub
set_local 4
get_local 3
get_local 1
f32.sub
tee_local 5
get_local 5
f32.mul
get_local 4
get_local 4
f32.mul
f32.add
f32.sqrt
)
(func
(export "length")
(param f64 f64 f64 f64)
(result f64)
(local f64 f64 f64)
get_local 2
get_local 0
f64.sub
set_local 4
get_local 3
get_local 1
f64.sub
tee_local 5
get_local 5
f64.mul
get_local 4
get_local 4
f64.mul
f64.add
f64.sqrt
)
)
As compiled wasm in hex string (Note does not include name section) and loaded using WebAssembly.compile. Exported functions then run against Javascript function len (in below snippet)
// hex of above without the name section
const asm = `0061736d0100000001110260047d7d7d7d017d60047c7c7c7c017c0303020001071402076c656e677468460000066c656e67746800010a3b021c01037d2002200093210420032001932205200594200420049492910b1c01037c20022000a1210420032001a122052005a220042004a2a09f0b`
const bin = new Uint8Array(asm.length >> 1);
for(var i = 0; i < asm.length; i+= 2){ bin[i>>1] = parseInt(asm.substr(i,2),16) }
var length,lengthF;
WebAssembly.compile(bin).then(module => {
const wasmInstance = new WebAssembly.Instance(module, {});
lengthF = wasmInstance.exports.lengthF;
length = wasmInstance.exports.length;
});
// test values are const (same result if from array or literals)
const a1 = rand(-100000,100000);
const a2 = rand(-100000,100000);
const a3 = rand(-100000,100000);
const a4 = rand(-100000,100000);
// javascript version of function
function len(x,y,x1,y1){
var nx = x1 - x;
var ny = y1 - y;
return Math.sqrt(nx * nx + ny * ny);
}
And the test code is the same for all 3 functions and run in strict mode.
tests : [{
func : function (){
var i;
for (i = 0; i < 100000; i += 1) {
length(a1,a2,a3,a4);
}
},
name : "length64",
},{
func : function (){
var i;
for (i = 0; i < 100000; i += 1) {
lengthF(a1,a2,a3,a4);
}
},
name : "length32",
},{
func : function (){
var i;
for (i = 0; i < 100000; i += 1) {
len(a1,a2,a3,a4);
}
},
name : "lengthNative",
}
]
The test results on FireFox are
/*
=======================================
Performance test. : WebAssm V Javascript
Use strict....... : true
Data view........ : false
Duplicates....... : 4
Cycles........... : 34
Samples per cycle : 100
Tests per Sample. : undefined
---------------------------------------------
Test : 'length64'
Mean : 26359µs ±128µs (*) 1128 samples
---------------------------------------------
Test : 'length32'
Mean : 27456µs ±109µs (*) 1144 samples
---------------------------------------------
Test : 'lengthNative'
Mean : 106µs ±2µs (*) 1128 samples
-All ----------------------------------------
Mean : 18.018ms Totals time : 61262.240ms 3400 samples
(*) Error rate approximation does not represent the variance.
*/

Andreas describes a number of good reasons why the JavaScript implementation was initially observed to be x300 faster. However, there are a number of other issues with your code.
This is a classic 'micro benchmark', i.e. the code that you are testing is so small, that the other overheads within your test loop are a significant factor. For example, there is an overhead in calling WebAssembly from JavaScript, which will factor in your results. What are you trying to measure? raw processing speed? or the overhead of the language boundary?
Your results vary wildly, from x300 to x2, due to small changes in your test code. Again, this is a micro benchmark issue. Others have seen the same when using this approach to measure performance, for example this post claims wasm is x84 faster, which is clearly wrong!
The current WebAssembly VM is very new, and an MVP. It will get faster. Your JavaScript VM has had 20 years to reach its current speed. The performance of the JS <=> wasm boundary is being worked on and optimised right now.
For a more definitive answer, see the joint paper from the WebAssembly team, which outlines an expected runtime performance gain of around 30%
Finally, to answer your point:
Whats the point of WebAssembly if it does not optimise
I think you have misconceptions around what WebAssembly will do for you. Based on the paper above, the runtime performance optimisations are quite modest. However, there are still a number of performance advantages:
Its compact binary format mean and low level nature means the browser can load, parse and compile the code much faster than JavaScript. It is anticipated that WebAssembly can be compiled faster than your browser can download it.
WebAssembly has a predictable runtime performance. With JavaScript the performance generally increases with each iteration as it is further optimised. It can also decrease due to se-optimisation.
There are also a number of non-performance related advantages too.
For a more realistic performance measurement, take a look at:
Its use within Figma
Results from using it with PDFKit
Both are practical, production codebases.

The JS engine can apply a lot of dynamic optimisations to this example:
Perform all calculations with integers and only convert to double for the final call to Math.sqrt.
Inline the call to the len function.
Hoist the computation out of the loop, since it always computes the same thing.
Recognise that the loop is left empty and eliminate it entirely.
Recognise that the result is never returned from the testing function, and hence remove the entire body of the test function.
All but (4) apply even if you add the result of every call. With (5) the end result is an empty function either way.
With Wasm an engine cannot do most of these steps, because it cannot inline across language boundaries (at least no engine does that today, AFAICT). Also, for Wasm it is assumed that the producing (offline) compiler has already performed relevant optimisations, so a Wasm JIT tends to be less aggressive than one for JavaScript, where static optimisation is impossible.

Serious answer
It seemed like
WebAssembly is far from a ready technology.
actually did play a role in this, and performance of calling WASM from JS in Firefox was improved in late 2018.
Running your benchmarks in a current FF/Chromium yields results like "Calling the WASM implementation from JS is 4-10 times slower than calling the JS implementation from JS". Still, it seems like engines don't inline across WASM/JS borders, and the overhead of having to call vs. not having to call is significant (as the other answers already pointed out).
Mocking answer
Your benchmarks are all wrong. It turns out that JS is actually 8-40 times (FF, Chrome) slower than WASM. WTF, JS is soo slooow.
Do I intend to prove that? Of course (not).
First, I re-implement your benchmarking code in C:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static double lengthC(double x, double y, double x1, double y1) {
double nx = x1 - x;
double ny = y1 - y;
return sqrt(nx * nx + ny * ny);
}
double lengthArrayC(double* a, size_t length) {
double c = 0;
for (size_t i = 0; i < length; i++) {
double a1 = a[i + 0];
double a2 = a[i + 1];
double a3 = a[i + 2];
double a4 = a[i + 3];
c += lengthC(a1,a2,a3,a4);
c += lengthC(a2,a3,a4,a1);
c += lengthC(a3,a4,a1,a2);
c += lengthC(a4,a1,a2,a3);
}
return c;
}
#ifdef __wasm__
__attribute__((import_module("js"), import_name("len")))
double lengthJS(double x, double y, double x1, double y1);
double lengthArrayJS(double* a, size_t length) {
double c = 0;
for (size_t i = 0; i < length; i++) {
double a1 = a[i + 0];
double a2 = a[i + 1];
double a3 = a[i + 2];
double a4 = a[i + 3];
c += lengthJS(a1,a2,a3,a4);
c += lengthJS(a2,a3,a4,a1);
c += lengthJS(a3,a4,a1,a2);
c += lengthJS(a4,a1,a2,a3);
}
return c;
}
__attribute__((import_module("bench"), import_name("now")))
double now();
__attribute__((import_module("bench"), import_name("result")))
void printtime(int benchidx, double ns);
#else
void printtime(int benchidx, double ns) {
if (benchidx == 1) {
printf("C: %f ns\n", ns);
} else if (benchidx == 0) {
printf("avoid the optimizer: %f\n", ns);
} else {
fprintf(stderr, "Unknown benchmark: %d", benchidx);
exit(-1);
}
}
double now() {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
} else {
return sqrt(-1);
}
}
#endif
#define iters 1000000
double a[iters+3];
int main() {
int bigCount = 0;
srand(now());
for (size_t i = 0; i < iters + 3; i++)
a[i] = (double)rand()/RAND_MAX*2e5-1e5;
for (int i = 0; i < 10; i++) {
double startTime, endTime;
double c;
startTime = now();
c = lengthArrayC(a, iters);
endTime = now();
bigCount = (bigCount + (int64_t)c) % 1000;
printtime(1, (endTime - startTime) * 1e9 / iters / 4);
#ifdef __wasm__
startTime = now();
c = lengthArrayJS(a, iters);
endTime = now();
bigCount = (bigCount + (int64_t)c) % 1000;
printtime(2, (endTime - startTime) * 1e9 / iters / 4);
#endif
}
printtime(0, bigCount);
return 0;
}
Compile it with clang 12.0.1:
clang -O3 -target wasm32-wasi --sysroot /opt/wasi-sdk/wasi-sysroot/ foo2.c -o foo2.wasm
And provide it with a length function from JS via imports:
"use strict";
(async (wasm) => {
const wasmbytes = new Uint8Array(wasm.length);
for (var i in wasm)
wasmbytes[i] = wasm.charCodeAt(i);
(await WebAssembly.instantiate(wasmbytes, {
js: {
len: function (x,y,x1,y1) {
var nx = x1 - x;
var ny = y1 - y;
return Math.sqrt(nx * nx + ny * ny);
}
},
bench: {
now: () => window.performance.now() / 1e3,
result: (bench, ns) => {
let name;
if (bench == 1) { name = "C" }
else if (bench == 2) { name = "JS" }
else if (bench == 0) { console.log("Optimizer confuser: " + ns); /*not really necessary*/; return; }
else { throw "unknown bench"; }
console.log(name + ": " + ns + " ns");
},
},
})).instance.exports._start();
})(atob('AGFzbQEAAAABFQRgBHx8fHwBfGAAAXxgAn98AGAAAAIlAwJqcwNsZW4AAAViZW5jaANub3cAAQViZW5jaAZyZXN1bHQAAgMCAQMFAwEAfAcTAgZtZW1vcnkCAAZfc3RhcnQAAwr2BAHzBAMIfAJ/An5BmKzoAwJ/EAEiA0QAAAAAAADwQWMgA0QAAAAAAAAAAGZxBEAgA6sMAQtBAAtBAWutNwMAQejbl3whCANAQZis6ANBmKzoAykDAEKt/tXk1IX9qNgAfkIBfCIKNwMAIAhBmKzoA2ogCkIhiKe3RAAAwP///99Bo0QAAAAAAGoIQaJEAAAAAABq+MCgOQMAIAhBCGoiCA0ACwNAEAEhBkGQCCsDACEBQYgIKwMAIQRBgAgrAwAhAEQAAAAAAAAAACECQRghCANAIAQhAyABIgQgAKEiASABoiIHIAMgCEGACGorAwAiAaEiBSAFoiIFoJ8gACAEoSIAIACiIgAgBaCfIAAgASADoSIAIACiIgCgnyACIAcgAKCfoKCgoCECIAMhACAIQQhqIghBmKToA0cNAAtBARABIAahRAAAAABlzc1BokQAAAAAgIQuQaNEAAAAAAAA0D+iEAICfiACmUQAAAAAAADgQ2MEQCACsAwBC0KAgICAgICAgIB/CyALfEQAAAAAAAAAACECQYDcl3whCBABIQMDQCACIAhBgKzoA2orAwAiBSAIQYis6ANqKwMAIgEgCEGQrOgDaisDACIAIAhBmKzoA2orAwAiBBAAoCABIAAgBCAFEACgIAAgBCAFIAEQAKAgBCAFIAEgABAAoCECIAhBCGoiCA0AC0ECEAEgA6FEAAAAAGXNzUGiRAAAAACAhC5Bo0QAAAAAAADQP6IQAkLoB4EhCgJ+IAKZRAAAAAAAAOBDYwRAIAKwDAELQoCAgICAgICAgH8LIAp8QugHgSELIAlBAWoiCUEKRw0AC0EAIAuntxACCwB2CXByb2R1Y2VycwEMcHJvY2Vzc2VkLWJ5AQVjbGFuZ1YxMS4wLjAgKGh0dHBzOi8vZ2l0aHViLmNvbS9sbHZtL2xsdm0tcHJvamVjdCAxNzYyNDliZDY3MzJhODA0NGQ0NTcwOTJlZDkzMjc2ODcyNGE2ZjA2KQ=='))
Now, calling the JS function from WASM is unsurprisingly a lot slower than calling the WASM function from WASM. (In fact, WASM→WASM it isn't calling. You can see the f64.sqrt being inlined into _start.)
(One last interesting datapoint is that WASM→WASM and JS→JS seem to have about the same cost (about 1.5 ns per inlined length(…) on my E3-1280). Disclaimer: It's entirely possible that my benchmark is even more broken than the original question.)
Conclusion
WASM isn't slow, crossing the border is. For now and the foreseeable future, don't put things into WASM unless they're a significant computational task. (And even then, it depends. Sometimes, JS engines are really smart. Sometimes.)

Related

Programmatically solving Sam Loyd's Battle of Hastings puzzle - performance issues with BigInt

I'm having performance issues when trying to check whether integer n is a perfect square (sqrt is a whole number) when using BigInt. Using normal numbers below Number.MAX_SAFE_INTEGER gives reasonable performance, but attempting to use BigInt even with the same number range causes a huge performance hit.
The program solves the Battle of Hastings perfect square riddle put forth by Sam Loyd whereby my program iterates over the set of real numbers n (in this example, up to 7,000,000) to find instances where variable y is a whole number (perfect square). I'm interested in the original square root of one of the 13 perfect squares where this condition is satisfied, which is what my code generates (there's more than one).
Assuming y^2 < Number.MAX_SAFE_INTEGER which is 2^53 – 1, this can be done without BigInt and runs in ~60ms on my machine:
const limit = 7_000_000;
var a = [];
console.time('regular int');
for (let n = 1; n < limit; n++) {
if (Math.sqrt(Math.pow(n, 2) * 13 + 1) % 1 === 0)
a.push(n);
}
console.log(a.join(', '));
console.timeEnd('regular int');
Being able to use BigInt would mean I could test for numbers much higher than the inherent number variable limit 2^53 - 1, but BigInt seems inherently slower; unusably so. To test whether a BigInt is a perfect square, I have to use a third party library as Math.sqrt doesn't exist for BigInt such that I can check if the root is perfect, as all sqrt returns a floor value. I adapted functions for this from a NodeJS library, bigint-isqrt and bigint-is-perfect-square.
Thus, using BigInt with the same limit of 7,000,000 runs 35x slower:
var integerSQRT = function(value) {
if (value < 2n)
return value;
if (value < 16n)
return BigInt(Math.sqrt(Number(value)) | 0);
let x0, x1;
if (value < 4503599627370496n)
x1 = BigInt(Math.sqrt(Number(value))|0) - 3n;
else {
let vlen = value.toString().length;
if (!(vlen & 1))
x1 = 10n ** (BigInt(vlen / 2));
else
x1 = 4n * 10n ** (BigInt((vlen / 2) | 0));
}
do {
x0 = x1;
x1 = ((value / x0) + x0) >> 1n;
} while ((x0 !== x1 && x0 !== (x1 - 1n)));
return x0;
}
function perfectSquare(n) {
// Divide n by 4 while divisible
while ((n & 3n) === 0n && n !== 0n) {
n >>= 2n;
}
// So, for now n is not divisible by 2
// The only possible residual modulo 8 for such n is 1
if ((n & 7n) !== 1n)
return false;
return n === integerSQRT(n) ** 2n;
}
const limit = 7_000_000;
var a = [];
console.time('big int');
for (let n = 1n; n < limit; n++) {
if (perfectSquare(((n ** 2n) * 13n) + 1n))
a.push(n);
}
console.log(a.join(', '));
console.timeEnd('big int');
Ideally I'm interested in doing this with a much higher limit than 7 million, but I'm unsure whether I can optimise the BigInt version any further. Any suggestions?
You may be pleased to learn that some recent improvements on V8 have sped up the BigInt version quite a bit; with a recent V8 build I'm seeing your BigInt version being about 12x slower than the Number version.
A remaining challenge is that implementations of BigInt-sqrt are typically based on Newton iteration and hence need an estimate for a starting value, which should be near the final result, so about half as wide as the input, which is given by log2(X) or bitLength(X). Until this proposal gets anywhere, that can best be done by converting the BigInt to a string and taking that string's length, which is fairly expensive.
To get faster right now, #Ouroborus' idea is great. I was curious how fast it would be, so I implemented it:
(function betterAlgorithm() {
const limit = 7_000_000n;
var a = [];
console.time('better algorithm');
let m = 1n;
let m_squared = 1n;
for (let n = 1n; n < limit; n += 1n) {
let y_squared = n * n * 13n + 1n;
while (y_squared > m_squared) {
m += 1n;
m_squared = m * m;
}
if (y_squared === m_squared) {
a.push(n);
}
}
console.log(a.join(', '));
console.timeEnd('better algorithm');
})();
As a particular short-term detail, this uses += 1n instead of ++, because as of today, V8 hasn't yet gotten around to optimizing ++ for BigInts. This difference should disappear eventually (hopefully soon).
On my machine, this version takes only about 4x as much time as your original Number-based implementation.
For larger numbers, I would expect some gains from replacing the multiplications with additions (based on the observation that the delta between consecutive square numbers grows linearly), but for small-ish upper limits that appears to be a bit slower. If you want to toy around with it, this snippet describes the idea:
let m_squared = 1n; // == 1*1
let m_squared_delta = 3n; // == 2*2 - 1*1
let y_squared = 14n; // == 1*1*13+1
let y_squared_delta = 39n; // == 2*2*13+1 - 1*1*13+1
for (let n = 1; n < limit; n++) {
while (y_squared > m_squared) {
m_squared += m_squared_delta;
m_squared_delta += 2n;
}
if (y_squared === m_squared) {
a.push(n);
}
y_squared += y_squared_delta;
y_squared_delta += 26n;
}
The earliest where this could possibly pay off is when the results exceed 2n**64n; I wouldn't be surprised if it wasn't measurable before 2n**256n or so.

Random from array seeded with today's date in JavaScript [duplicate]

Is it possible to seed the random number generator (Math.random) in JavaScript?
No, it is not possible to seed Math.random(). The ECMAScript specification is intentionally vague on the subject, providing no means for seeding nor require that browsers even use the same algorithm. So such a function must be externally provided, which thankfully isn't too difficult.
I've implemented a number of good, short and fast Pseudorandom number generator (PRNG) functions in plain JavaScript. All of them can be seeded and provide high quality numbers. These are not intended for security purposes--if you need a seedable CSPRNG, look into ISAAC.
First of all, take care to initialize your PRNGs properly. To keep things simple, the generators below have no built-in seed generating procedure, but accept one or more 32-bit numbers as the initial seed state of the PRNG. Similar or sparse seeds (e.g. a simple seed of 1 and 2) have low entropy, and can cause correlations or other randomness quality issues, sometimes resulting in the output having similar properties (such as randomly generated levels being similar). To avoid this, it is best practice to initialize PRNGs with a well-distributed, high entropy seed and/or advancing past the first 15 or so numbers.
There are many ways to do this, but here are two methods. Firstly, hash functions are very good at generating seeds from short strings. A good hash function will generate very different results even when two strings are similar, so you don't have to put much thought into the string. Here's an example hash function:
function cyrb128(str) {
let h1 = 1779033703, h2 = 3144134277,
h3 = 1013904242, h4 = 2773480762;
for (let i = 0, k; i < str.length; i++) {
k = str.charCodeAt(i);
h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
}
h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
return [(h1^h2^h3^h4)>>>0, (h2^h1)>>>0, (h3^h1)>>>0, (h4^h1)>>>0];
}
Calling cyrb128 will produce a 128-bit hash value from a string which can be used to seed a PRNG. Here's how you might use it:
// Create cyrb128 state:
var seed = cyrb128("apples");
// Four 32-bit component hashes provide the seed for sfc32.
var rand = sfc32(seed[0], seed[1], seed[2], seed[3]);
// Only one 32-bit component hash is needed for mulberry32.
var rand = mulberry32(seed[0]);
// Obtain sequential random numbers like so:
rand();
rand();
Note: If you want a slightly more robust 128-bit hash, consider MurmurHash3_x86_128, it's more thorough, but intended for use with large arrays.
Alternatively, simply choose some dummy data to pad the seed with, and advance the generator beforehand a few times (12-20 iterations) to mix the initial state thoroughly. This has the benefit of being simpler, and is often used in reference implementations of PRNGs, but it does limit the number of initial states:
var seed = 1337 ^ 0xDEADBEEF; // 32-bit seed with optional XOR value
// Pad seed with Phi, Pi and E.
// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number
var rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed);
for (var i = 0; i < 15; i++) rand();
Note: the output of these PRNG functions produce a positive 32-bit number (0 to 232-1) which is then converted to a floating-point number between 0-1 (0 inclusive, 1 exclusive) equivalent to Math.random(), if you want random numbers of a specific range, read this article on MDN. If you only want the raw bits, simply remove the final division operation.
JavaScript numbers can only represent whole integers up to 53-bit resolution. And when using bitwise operations, this is reduced to 32. Modern PRNGs in other languages often use 64-bit operations, which require shims when porting to JS that can drastically reduce performance. The algorithms here only use 32-bit operations, as it is directly compatible with JS.
Now, onward to the the generators. (I maintain the full list with references and license info here)
sfc32 (Simple Fast Counter)
sfc32 is part of the PractRand random number testing suite (which it passes of course). sfc32 has a 128-bit state and is very fast in JS.
function sfc32(a, b, c, d) {
return function() {
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
var t = (a + b) | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
}
}
You may wonder what the | 0 and >>>= 0 are for. These are essentially 32-bit integer casts, used for performance optimizations. Number in JS are basically floats, but during bitwise operations, they switch into a 32-bit integer mode. This mode is processed faster by JS interpreters, but any multiplication or addition will cause it to switch back to a float, resulting in a performance hit.
Mulberry32
Mulberry32 is a simple generator with a 32-bit state, but is extremely fast and has good quality randomness (author states it passes all tests of gjrand testing suite and has a full 232 period, but I haven't verified).
function mulberry32(a) {
return function() {
var t = a += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
}
I would recommend this if you just need a simple but decent PRNG and don't need billions of random numbers (see Birthday problem).
xoshiro128**
As of May 2018, xoshiro128** is the new member of the Xorshift family, by Vigna & Blackman (professor Vigna was also responsible for the Xorshift128+ algorithm powering most Math.random implementations under the hood). It is the fastest generator that offers a 128-bit state.
function xoshiro128ss(a, b, c, d) {
return function() {
var t = b << 9, r = a * 5; r = (r << 7 | r >>> 25) * 9;
c ^= a; d ^= b;
b ^= c; a ^= d; c ^= t;
d = d << 11 | d >>> 21;
return (r >>> 0) / 4294967296;
}
}
The authors claim it passes randomness tests well (albeit with caveats). Other researchers have pointed out that it fails some tests in TestU01 (particularly LinearComp and BinaryRank). In practice, it should not cause issues when floats are used (such as in these implementations), but may cause issues if relying on the raw lowest order bit.
JSF (Jenkins' Small Fast)
This is JSF or 'smallprng' by Bob Jenkins (2007), who also made ISAAC and SpookyHash. It passes PractRand tests and should be quite fast, although not as fast as sfc32.
function jsf32(a, b, c, d) {
return function() {
a |= 0; b |= 0; c |= 0; d |= 0;
var t = a - (b << 27 | b >>> 5) | 0;
a = b ^ (c << 17 | c >>> 15);
b = c + d | 0;
c = d + t | 0;
d = a + t | 0;
return (d >>> 0) / 4294967296;
}
}
No, it is not possible to seed Math.random(), but it's fairly easy to write your own generator, or better yet, use an existing one.
Check out: this related question.
Also, see David Bau's blog for more information on seeding.
NOTE: Despite (or rather, because of) succinctness and apparent elegance, this algorithm is by no means a high-quality one in terms of randomness. Look for e.g. those listed in this answer for better results.
(Originally adapted from a clever idea presented in a comment to another answer.)
var seed = 1;
function random() {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
You can set seed to be any number, just avoid zero (or any multiple of Math.PI).
The elegance of this solution, in my opinion, comes from the lack of any "magic" numbers (besides 10000, which represents about the minimum amount of digits you must throw away to avoid odd patterns - see results with values 10, 100, 1000). Brevity is also nice.
It's a bit slower than Math.random() (by a factor of 2 or 3), but I believe it's about as fast as any other solution written in JavaScript.
No, but here's a simple pseudorandom generator, an implementation of Multiply-with-carry I adapted from Wikipedia (has been removed since):
var m_w = 123456789;
var m_z = 987654321;
var mask = 0xffffffff;
// Takes any integer
function seed(i) {
m_w = (123456789 + i) & mask;
m_z = (987654321 - i) & mask;
}
// Returns number between 0 (inclusive) and 1.0 (exclusive),
// just like Math.random().
function random()
{
m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}
Antti Sykäri's algorithm is nice and short. I initially made a variation that replaced JavaScript's Math.random when you call Math.seed(s), but then Jason commented that returning the function would be better:
Math.seed = function(s) {
return function() {
s = Math.sin(s) * 10000; return s - Math.floor(s);
};
};
// usage:
var random1 = Math.seed(42);
var random2 = Math.seed(random1());
Math.random = Math.seed(random2());
This gives you another functionality that JavaScript doesn't have: multiple independent random generators. That is especially important if you want to have multiple repeatable simulations running at the same time.
Please see Pierre L'Ecuyer's work going back to the late 1980s and early 1990s. There are others as well. Creating a (pseudo) random number generator on your own, if you are not an expert, is pretty dangerous, because there is a high likelihood of either the results not being statistically random or in having a small period. Pierre (and others) have put together some good (pseudo) random number generators that are easy to implement. I use one of his LFSR generators.
https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf
Combining some of the previous answers, this is the seedable random function you are looking for:
Math.seed = function(s) {
var mask = 0xffffffff;
var m_w = (123456789 + s) & mask;
var m_z = (987654321 - s) & mask;
return function() {
m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}
}
var myRandomFunction = Math.seed(1234);
var randomNumber = myRandomFunction();
It's not possible to seed the builtin Math.random function, but it is possible to implement a high quality RNG in Javascript with very little code.
Javascript numbers are 64-bit floating point precision, which can represent all positive integers less than 2^53. This puts a hard limit to our arithmetic, but within these limits you can still pick parameters for a high quality Lehmer / LCG random number generator.
function RNG(seed) {
var m = 2**35 - 31
var a = 185852
var s = seed % m
return function () {
return (s = s * a % m) / m
}
}
Math.random = RNG(Date.now())
If you want even higher quality random numbers, at the cost of being ~10 times slower, you can use BigInt for the arithmetic and pick parameters where m is just able to fit in a double.
function RNG(seed) {
var m_as_number = 2**53 - 111
var m = 2n**53n - 111n
var a = 5667072534355537n
var s = BigInt(seed) % m
return function () {
return Number(s = s * a % m) / m_as_number
}
}
See this paper by Pierre l'Ecuyer for the parameters used in the above implementations:
https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
And whatever you do, avoid all the other answers here that use Math.sin!
To write your own pseudo random generator is quite simple.
The suggestion of Dave Scotese is useful but, as pointed out by others, it is not quite uniformly distributed.
However, it is not because of the integer arguments of sin. It's simply because of the range of sin, which happens to be a one dimensional projection of a circle. If you would take the angle of the circle instead it would be uniform.
So instead of sin(x) use arg(exp(i * x)) / (2 * PI).
If you don't like the linear order, mix it a bit up with xor. The actual factor doesn't matter that much either.
To generate n pseudo random numbers one could use the code:
function psora(k, n) {
var r = Math.PI * (k ^ n)
return r - Math.floor(r)
}
n = 42; for(k = 0; k < n; k++) console.log(psora(k, n))
Please also note that you cannot use pseudo random sequences when real entropy is needed.
Many people who need a seedable random-number generator in Javascript these days are using David Bau's seedrandom module.
Math.random no, but the ran library solves this. It has almost all distributions you can imagine and supports seeded random number generation. Example:
ran.core.seed(0)
myDist = new ran.Dist.Uniform(0, 1)
samples = myDist.sample(1000)
Here's the adopted version of Jenkins hash, borrowed from here
export function createDeterministicRandom(): () => number {
let seed = 0x2F6E2B1;
return function() {
// Robert Jenkins’ 32 bit integer hash function
seed = ((seed + 0x7ED55D16) + (seed << 12)) & 0xFFFFFFFF;
seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
seed = ((seed + 0x165667B1) + (seed << 5)) & 0xFFFFFFFF;
seed = ((seed + 0xD3A2646C) ^ (seed << 9)) & 0xFFFFFFFF;
seed = ((seed + 0xFD7046C5) + (seed << 3)) & 0xFFFFFFFF;
seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
return (seed & 0xFFFFFFF) / 0x10000000;
};
}
You can use it like this:
const deterministicRandom = createDeterministicRandom()
deterministicRandom()
// => 0.9872818551957607
deterministicRandom()
// => 0.34880331158638
No, like they said it is not possible to seed Math.random()
but you can install external package which make provision for that. i used these package which can be install using these command
npm i random-seed
the example is gotten from the package documentation.
var seed = 'Hello World',
rand1 = require('random-seed').create(seed),
rand2 = require('random-seed').create(seed);
console.log(rand1(100), rand2(100));
follow the link for documentation https://www.npmjs.com/package/random-seed
SIN(id + seed) is a very interesting replacement for RANDOM functions that cannot be seeded like SQLite:
https://stackoverflow.com/a/75089040/7776828
Most of the answers here produce biased results. So here's a tested function based on seedrandom library from github:
!function(f,a,c){var s,l=256,p="random",d=c.pow(l,6),g=c.pow(2,52),y=2*g,h=l-1;function n(n,t,r){function e(){for(var n=u.g(6),t=d,r=0;n<g;)n=(n+r)*l,t*=l,r=u.g(1);for(;y<=n;)n/=2,t/=2,r>>>=1;return(n+r)/t}var o=[],i=j(function n(t,r){var e,o=[],i=typeof t;if(r&&"object"==i)for(e in t)try{o.push(n(t[e],r-1))}catch(n){}return o.length?o:"string"==i?t:t+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[n,S(a)]:null==n?function(){try{var n;return s&&(n=s.randomBytes)?n=n(l):(n=new Uint8Array(l),(f.crypto||f.msCrypto).getRandomValues(n)),S(n)}catch(n){var t=f.navigator,r=t&&t.plugins;return[+new Date,f,r,f.screen,S(a)]}}():n,3),o),u=new m(o);return e.int32=function(){return 0|u.g(4)},e.quick=function(){return u.g(4)/4294967296},e.double=e,j(S(u.S),a),(t.pass||r||function(n,t,r,e){return e&&(e.S&&v(e,u),n.state=function(){return v(u,{})}),r?(c[p]=n,t):n})(e,i,"global"in t?t.global:this==c,t.state)}function m(n){var t,r=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(r||(n=[r++]);e<l;)i[e]=e++;for(e=0;e<l;e++)i[e]=i[o=h&o+n[e%r]+(t=i[e])],i[o]=t;(u.g=function(n){for(var t,r=0,e=u.i,o=u.j,i=u.S;n--;)t=i[e=h&e+1],r=r*l+i[h&(i[e]=i[o=h&o+t])+(i[o]=t)];return u.i=e,u.j=o,r})(l)}function v(n,t){return t.i=n.i,t.j=n.j,t.S=n.S.slice(),t}function j(n,t){for(var r,e=n+"",o=0;o<e.length;)t[h&o]=h&(r^=19*t[h&o])+e.charCodeAt(o++);return S(t)}function S(n){return String.fromCharCode.apply(0,n)}if(j(c.random(),a),"object"==typeof module&&module.exports){module.exports=n;try{s=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd?define(function(){return n}):c["seed"+p]=n}("undefined"!=typeof self?self:this,[],Math);
function randIntWithSeed(seed, max=1) {
/* returns a random number between [0,max] including zero and max
seed can be either string or integer */
return Math.round(new Math.seedrandom('seed' + seed)()) * max
}
test for true randomness of this code: https://es6console.com/kkjkgur2/
There are plenty of good answers here but I had a similar issue with the additional requirement that I would like portability between Java's random number generator and whatever I ended up using in JavaScript.
I found the java-random package
These two pieces of code had identical output assuming the seed is the same:
Java:
Random randomGenerator = new Random(seed);
int randomInt;
for (int i=0; i<10; i++) {
randomInt = randomGenerator.nextInt(50);
System.out.println(randomInt);
}
JavaScript:
let Random = require('java-random');
let rng = new Random(seed);
for (let i=0; i<10; i++) {
let val = rng.nextInt(50);
console.log(val);
}
I have written a function that returns a seeded random number, it uses Math.sin to have a long random number and uses the seed to pick numbers from that.
Use :
seedRandom("k9]:2#", 15)
it will return your seeded number
the first parameter is any string value ; your seed.
the second parameter is how many digits will return.
function seedRandom(inputSeed, lengthOfNumber){
var output = "";
var seed = inputSeed.toString();
var newSeed = 0;
var characterArray = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','y','x','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','U','R','S','T','U','V','W','X','Y','Z','!','#','#','$','%','^','&','*','(',')',' ','[','{',']','}','|',';',':',"'",',','<','.','>','/','?','`','~','-','_','=','+'];
var longNum = "";
var counter = 0;
var accumulator = 0;
for(var i = 0; i < seed.length; i++){
var a = seed.length - (i+1);
for(var x = 0; x < characterArray.length; x++){
var tempX = x.toString();
var lastDigit = tempX.charAt(tempX.length-1);
var xOutput = parseInt(lastDigit);
addToSeed(characterArray[x], xOutput, a, i);
}
}
function addToSeed(character, value, a, i){
if(seed.charAt(i) === character){newSeed = newSeed + value * Math.pow(10, a)}
}
newSeed = newSeed.toString();
var copy = newSeed;
for(var i=0; i<lengthOfNumber*9; i++){
newSeed = newSeed + copy;
var x = Math.sin(20982+(i)) * 10000;
var y = Math.floor((x - Math.floor(x))*10);
longNum = longNum + y.toString()
}
for(var i=0; i<lengthOfNumber; i++){
output = output + longNum.charAt(accumulator);
counter++;
accumulator = accumulator + parseInt(newSeed.charAt(counter));
}
return(output)
}
A simple approach for a fixed seed:
function fixedrandom(p){
const seed = 43758.5453123;
return (Math.abs(Math.sin(p)) * seed)%1;
}
In PHP, there is function srand(seed) which generate fixed random value for particular seed.
But, in JS, there is no such inbuilt function.
However, we can write simple and short function.
Step 1: Choose some Seed (Fix Number).
var seed = 100;
Number should be Positive Integer and greater than 1, further explanation in Step 2.
Step 2: Perform Math.sin() function on Seed, it will give sin value of that number. Store this value in variable x.
var x;
x = Math.sin(seed); // Will Return Fractional Value between -1 & 1 (ex. 0.4059..)
sin() method returns a Fractional value between -1 and 1.And we don't need Negative value, therefore, in first step choose number greater than 1.
Step 3: Returned Value is a Fractional value between -1 and 1. So mulitply this value with 10 for making it more than 1.
x = x * 10; // 10 for Single Digit Number
Step 4: Multiply the value with 10 for additional digits
x = x * 10; // Will Give value between 10 and 99 OR
x = x * 100; // Will Give value between 100 and 999
Multiply as per requirement of digits.
The result will be in decimal.
Step 5: Remove value after Decimal Point by Math's Round (Math.round()) Method.
x = Math.round(x); // This will give Integer Value.
Step 6: Turn Negative Values into Positive (if any) by Math.abs method
x = Math.abs(x); // Convert Negative Values into Positive(if any)
Explanation End.Final Code
var seed = 111; // Any Number greater than 1
var digit = 10 // 1 => single digit, 10 => 2 Digits, 100 => 3 Digits and so. (Multiple of 10)
var x; // Initialize the Value to store the result
x = Math.sin(seed); // Perform Mathematical Sin Method on Seed.
x = x * 10; // Convert that number into integer
x = x * digit; // Number of Digits to be included
x = Math.round(x); // Remove Decimals
x = Math.abs(x); // Convert Negative Number into Positive
Clean and Optimized Functional Code
function random_seed(seed, digit = 1) {
var x = Math.abs(Math.round(Math.sin(seed++) * 10 * digit));
return x;
}
Then Call this function using
random_seed(any_number, number_of_digits)any_number is must and should be greater than 1.number_of_digits is optional parameter and if nothing passed, 1 Digit will return.
random_seed(555); // 1 Digit
random_seed(234, 1); // 1 Digit
random_seed(7895656, 1000); // 4 Digit
For a number between 0 and 100.
Number.parseInt(Math.floor(Math.random() * 100))

Recreating Blended Bisection and False Position algorithm from reference

I'm trying to recreate a blended bisection algorithm (Algorithm 3) from the website below (link takes you to exact section of the algorithm I'm referencing)
https://www.mdpi.com/2227-7390/7/11/1118/htm#sec3-mathematics-07-01118
I'm not quite sure if what I've typed out currently is correct and I'm stuck on line 29 of the algorithm from the website where I'm not sure what it means especially with the intersection symbol.
Code so far
/* Math function to test on */
function fn(x) {
//return x * x - x - 2; /* root for this is x = 2 */
return x*x*x-2; /* root for this is x = (2)^(1/3) */
}
function blendedMethod(a, b, eps, maxIterations, fn) {
let k = 0,
r, fa, fb, ba, bb, eps_a;
do {
let m = (a + b) * .5;
let eps_m = Math.abs(fn(m));
let fn_a = fn(a),
fn_r;
let s = a - ((fn_a * (b - a)) / (fn(b) - fn_a));
let eps_s = Math.abs(fn(s));
if (eps_m < eps_s) {
r = m;
fn_r = fn(r);
eps_a = eps_m;
if (fn_a * fn_r < 0) {
ba = a;
bb = r;
} else {
ba = r;
bb = b;
}
} else {
r = s;
fn_r = fn(r)
eps_a = eps_s;
if (fn_a * fn_r < 0) {
fa = a;
fb = r;
} else {
fa = r;
fb = b;
}
/* line 29 here! */
/* [a, b] = [ba, bb] ∩ [fa, fb] */
/* either fa,fb or ba,bb haven't yet been defined */
/* so this will fail with NaN */
a = Math.max(ba, fa);
b = Math.min(bb, fb);
}
r = r;
eps_a = Math.abs(fn_r)
k = k + 1;
} while (Math.abs(fn(r)) > eps || k < maxIterations)
/* think this is the root to return*/
return r;
}
console.log(blendedMethod(1,4,0.00001,1000,fn));
EDIT: Fixed some errors, only problem is that this algorithm defines either fa,fb or ba,bb inside the conditional statements without defining the other two. So by the time it comes to these calculations below, it fail with NaN and messes up for the next iterations.
a = Math.max(ba,fa);
b = Math.min(bb,fb);
You are right in that this intersection makes no sense. There is in every step only one sub-interval defined. As all intervals are successive nested subsets, the stale, old values of the interval that was not set in the current loop is still a superset of the new interval. The new interval could be directly set in each branch. Or the method selection branch could be totally separated from the interval selection branch.
The implementation is not very economic as 6 or more function values are computed where only 2 evaluations are needed. The idea being that the dominating factor in the time complexity are the function evaluations, so that a valid metric for any root finding algorithm is the number of function evaluations. To that end, always keep points and function value as pair, generate them as a pair, assign them as a pair.
let fn_a =f(a), fn_b=f(b)
do {
let m = (a + b) * .5;
let fm = f(m);
let s = a - (fn_a * (b - a)) / (fn_b - fn_a)
let fn_s = f(s);
let c,fn_c;
// method selection
if(Math.abs(fn_m) < Math.abs(fn_s)) {
c = m; fn_c = fn_m;
} else {
c = s; fn_c = fn_s;
}
// sub-interval selection
if( fn_a*fn_c > 0 ) {
a = c; fn_a = fn_c;
} else {
b = c; fn_b = fn_c;
}
while( Math.abs(b-a) > eps );
It is also not clear in what way the blended method avoids or alleviates the shortcomings of the basis algorithms. To avoid the stalling (deviation from a secant step) of the regula falsi method it would be better to introduce a stalling counter and apply a bisection step after 1 or 2 stalled steps. Or just simply alternate the false position and bisection steps. Both variants ensure the reduction of the bracketing interval.
Known effective modifications of the regula falsi method are on one hand the variations like the Illinois variant that add a weight factor to the function values, thus shifting the root approximation towards the repeated, stalled interval bound. On the other hand there are more general algorithms that combine the ideas of the bracketing interval and reverse interpolation like the Dekker and Brent methods.

How to generate trillions of random IDs quickly [duplicate]

How do I create GUIDs (globally-unique identifiers) in JavaScript? The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.
I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc.
[Edited 2021-10-16 to reflect latest best-practices for producing RFC4122-compliant UUIDs]
Most readers here will want to use the uuid module. It is well-tested and supported.
The crypto.randomUUID() function is an emerging standard that is supported in Node.js and an increasing number of browsers. However because new browser APIs are restricted to secure contexts this method is only available to pages served locally (localhost or 127.0.0.1) or over HTTPS. If you're interested in seeing this restriction lifted for crypto.randomUUID() you can follow this GitHub issue.
If neither of those work for you, there is this method (based on the original answer to this question):
function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
console.log(uuidv4());
Note: The use of any UUID generator that relies on Math.random() is strongly discouraged (including snippets featured in previous versions of this answer) for reasons best explained here. TL;DR: solutions based on Math.random() do not provide good uniqueness guarantees.
UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier), according to RFC 4122, are identifiers designed to provide certain uniqueness guarantees.
While it is possible to implement RFC-compliant UUIDs in a few lines of JavaScript code (e.g., see #broofa's answer, below) there are several common pitfalls:
Invalid id format (UUIDs must be of the form "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx", where x is one of [0-9, a-f] M is one of [1-5], and N is [8, 9, a, or b]
Use of a low-quality source of randomness (such as Math.random)
Thus, developers writing code for production environments are encouraged to use a rigorous, well-maintained implementation such as the uuid module.
I really like how clean Broofa's answer is, but it's unfortunate that poor implementations of Math.random leave the chance for collision.
Here's a similar RFC4122 version 4 compliant solution that solves that issue by offsetting the first 13 hex numbers by a hex portion of the timestamp, and once depleted offsets by a hex portion of the microseconds since pageload. That way, even if Math.random is on the same seed, both clients would have to generate the UUID the exact same number of microseconds since pageload (if high-perfomance time is supported) AND at the exact same millisecond (or 10,000+ years later) to get the same UUID:
function generateUUID() { // Public Domain/MIT
var d = new Date().getTime();//Timestamp
var d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16;//random number between 0 and 16
if(d > 0){//Use timestamp until depleted
r = (d + r)%16 | 0;
d = Math.floor(d/16);
} else {//Use microseconds since page-load if supported
r = (d2 + r)%16 | 0;
d2 = Math.floor(d2/16);
}
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
var onClick = function(){
document.getElementById('uuid').textContent = generateUUID();
}
onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID" onclick="onClick();">Generate UUID</button>
Here's a fiddle to test.
Modernized snippet for ES6
const generateUUID = () => {
let
d = new Date().getTime(),
d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
let r = Math.random() * 16;
if (d > 0) {
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
});
};
const onClick = (e) => document.getElementById('uuid').textContent = generateUUID();
document.getElementById('generateUUID').addEventListener('click', onClick);
onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID">Generate UUID</button>
broofa's answer is pretty slick, indeed - impressively clever, really... RFC4122 compliant, somewhat readable, and compact. Awesome!
But if you're looking at that regular expression, those many replace() callbacks, toString()'s and Math.random() function calls (where he's only using four bits of the result and wasting the rest), you may start to wonder about performance. Indeed, joelpt even decided to toss out an RFC for generic GUID speed with generateQuickGUID.
But, can we get speed and RFC compliance? I say, YES! Can we maintain readability? Well... Not really, but it's easy if you follow along.
But first, my results, compared to broofa, guid (the accepted answer), and the non-rfc-compliant generateQuickGuid:
Desktop Android
broofa: 1617ms 12869ms
e1: 636ms 5778ms
e2: 606ms 4754ms
e3: 364ms 3003ms
e4: 329ms 2015ms
e5: 147ms 1156ms
e6: 146ms 1035ms
e7: 105ms 726ms
guid: 962ms 10762ms
generateQuickGuid: 292ms 2961ms
- Note: 500k iterations, results will vary by browser/CPU.
So by my 6th iteration of optimizations, I beat the most popular answer by over 12 times, the accepted answer by over 9 times, and the fast-non-compliant answer by 2-3 times. And I'm still RFC 4122 compliant.
Interested in how? I've put the full source on http://jsfiddle.net/jcward/7hyaC/3/ and on https://jsben.ch/xczxS
For an explanation, let's start with broofa's code:
function broofa() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
console.log(broofa())
So it replaces x with any random hexadecimal digit, y with random data (except forcing the top two bits to 10 per the RFC spec), and the regex doesn't match the - or 4 characters, so he doesn't have to deal with them. Very, very slick.
The first thing to know is that function calls are expensive, as are regular expressions (though he only uses 1, it has 32 callbacks, one for each match, and in each of the 32 callbacks it calls Math.random() and v.toString(16)).
The first step toward performance is to eliminate the RegEx and its callback functions and use a simple loop instead. This means we have to deal with the - and 4 characters whereas broofa did not. Also, note that we can use String Array indexing to keep his slick String template architecture:
function e1() {
var u='',i=0;
while(i++<36) {
var c='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'[i-1],r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:v.toString(16)
}
return u;
}
console.log(e1())
Basically, the same inner logic, except we check for - or 4, and using a while loop (instead of replace() callbacks) gets us an almost 3X improvement!
The next step is a small one on the desktop but makes a decent difference on mobile. Let's make fewer Math.random() calls and utilize all those random bits instead of throwing 87% of them away with a random buffer that gets shifted out each iteration. Let's also move that template definition out of the loop, just in case it helps:
function e2() {
var u='',m='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',i=0,rb=Math.random()*0xffffffff|0;
while(i++<36) {
var c=m[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:v.toString(16);rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
}
return u
}
console.log(e2())
This saves us 10-30% depending on platform. Not bad. But the next big step gets rid of the toString function calls altogether with an optimization classic - the look-up table. A simple 16-element lookup table will perform the job of toString(16) in much less time:
function e3() {
var h='0123456789abcdef';
var k='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
/* same as e4() below */
}
function e4() {
var h=['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
var k=['x','x','x','x','x','x','x','x','-','x','x','x','x','-','4','x','x','x','-','y','x','x','x','-','x','x','x','x','x','x','x','x','x','x','x','x'];
var u='',i=0,rb=Math.random()*0xffffffff|0;
while(i++<36) {
var c=k[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:h[v];rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
}
return u
}
console.log(e4())
The next optimization is another classic. Since we're only handling four bits of output in each loop iteration, let's cut the number of loops in half and process eight bits in each iteration. This is tricky since we still have to handle the RFC compliant bit positions, but it's not too hard. We then have to make a larger lookup table (16x16, or 256) to store 0x00 - 0xFF, and we build it only once, outside the e5() function.
var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e5() {
var k=['x','x','x','x','-','x','x','-','4','x','-','y','x','-','x','x','x','x','x','x'];
var u='',i=0,rb=Math.random()*0xffffffff|0;
while(i++<20) {
var c=k[i-1],r=rb&0xff,v=c=='x'?r:(c=='y'?(r&0x3f|0x80):(r&0xf|0x40));
u+=(c=='-')?c:lut[v];rb=i%4==0?Math.random()*0xffffffff|0:rb>>8
}
return u
}
console.log(e5())
I tried an e6() that processes 16-bits at a time, still using the 256-element LUT, and it showed the diminishing returns of optimization. Though it had fewer iterations, the inner logic was complicated by the increased processing, and it performed the same on desktop, and only ~10% faster on mobile.
The final optimization technique to apply - unroll the loop. Since we're looping a fixed number of times, we can technically write this all out by hand. I tried this once with a single random variable, r, that I kept reassigning, and performance tanked. But with four variables assigned random data up front, then using the lookup table, and applying the proper RFC bits, this version smokes them all:
var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e7()
{
var d0 = Math.random()*0xffffffff|0;
var d1 = Math.random()*0xffffffff|0;
var d2 = Math.random()*0xffffffff|0;
var d3 = Math.random()*0xffffffff|0;
return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+
lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+
lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+
lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff];
}
console.log(e7())
Modualized: http://jcward.com/UUID.js - UUID.generate()
The funny thing is, generating 16 bytes of random data is the easy part. The whole trick is expressing it in string format with RFC compliance, and it's most tightly accomplished with 16 bytes of random data, an unrolled loop and lookup table.
I hope my logic is correct -- it's very easy to make a mistake in this kind of tedious bit work. But the outputs look good to me. I hope you enjoyed this mad ride through code optimization!
Be advised: my primary goal was to show and teach potential optimization strategies. Other answers cover important topics such as collisions and truly random numbers, which are important for generating good UUIDs.
Use:
let uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);
document.getElementById("unique").innerHTML =
Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
<div id="unique">
</div>
If IDs are generated more than 1 millisecond apart, they are 100% unique.
If two IDs are generated at shorter intervals, and assuming that the random method is truly random, this would generate IDs that are 99.99999999999999% likely to be globally unique (collision in 1 of 10^15).
You can increase this number by adding more digits, but to generate 100% unique IDs you will need to use a global counter.
If you need RFC compatibility, this formatting will pass as a valid version 4 GUID:
let u = Date.now().toString(16) + Math.random().toString(16) + '0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');
let u = Date.now().toString(16)+Math.random().toString(16)+'0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');
document.getElementById("unique").innerHTML = guid;
<div id="unique">
</div>
The above code follow the intention, but not the letter of the RFC. Among other discrepancies it's a few random digits short. (Add more random digits if you need it) The upside is that this is really fast :)
You can test validity of your GUID here
Here's some code based on RFC 4122, section 4.4 (Algorithms for Creating a UUID from Truly Random or Pseudo-Random Number).
function createUUID() {
// http://www.ietf.org/rfc/rfc4122.txt
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
}
This is the fastest GUID-like string generator method in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. It does not generate a standard-compliant GUID.
Ten million executions of this implementation take just 32.5 seconds, which is the fastest I've ever seen in a browser (the only solution without loops/iterations).
The function is as simple as:
/**
* Generates a GUID string.
* #returns {string} The generated GUID.
* #example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
* #author Slavik Meltser.
* #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 "000000000" (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 for 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"+"000000000"), and then cutting it off from the second index (third 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 four pieces, each piece divided into two types (or formats): XXXXXXXX and -XXXX-XXXX.
Now I'm building the GUID using these two types to assemble the GUID with call four 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.
Link to this post on my blog
Enjoy! :-)
Here is a totally non-compliant but very performant implementation to generate an ASCII-safe GUID-like unique identifier.
function generateQuickGuid() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
Generates 26 [a-z0-9] characters, yielding a UID that is both shorter and more unique than RFC compliant GUIDs. Dashes can be trivially added if human-readability matters.
Here are usage examples and timings for this function and several of this question's other answers. The timing was performed under Chrome m25, 10 million iterations each.
>>> generateQuickGuid()
"nvcjf1hs7tf8yyk4lmlijqkuo9"
"yq6gipxqta4kui8z05tgh9qeel"
"36dh5sec7zdj90sk2rx7pjswi2"
runtime: 32.5s
>>> GUID() // John Millikin
"7a342ca2-e79f-528e-6302-8f901b0b6888"
runtime: 57.8s
>>> regexGuid() // broofa
"396e0c46-09e4-4b19-97db-bd423774a4b3"
runtime: 91.2s
>>> createUUID() // Kevin Hakanson
"403aa1ab-9f70-44ec-bc08-5d5ac56bd8a5"
runtime: 65.9s
>>> UUIDv4() // Jed Schmidt
"f4d7d31f-fa83-431a-b30c-3e6cc37cc6ee"
runtime: 282.4s
>>> Math.uuid() // broofa
"5BD52F55-E68F-40FC-93C2-90EE069CE545"
runtime: 225.8s
>>> Math.uuidFast() // broofa
"6CB97A68-23A2-473E-B75B-11263781BBE6"
runtime: 92.0s
>>> Math.uuidCompact() // broofa
"3d7b7a06-0a67-4b67-825c-e5c43ff8c1e8"
runtime: 229.0s
>>> bitwiseGUID() // jablko
"baeaa2f-7587-4ff1-af23-eeab3e92"
runtime: 79.6s
>>>> betterWayGUID() // Andrea Turri
"383585b0-9753-498d-99c3-416582e9662c"
runtime: 60.0s
>>>> UUID() // John Fowler
"855f997b-4369-4cdb-b7c9-7142ceaf39e8"
runtime: 62.2s
Here is the timing code.
var r;
console.time('t');
for (var i = 0; i < 10000000; i++) {
r = FuncToTest();
};
console.timeEnd('t');
From sagi shkedy's technical blog:
function generateGuid() {
var result, i, j;
result = '';
for(j=0; j<32; j++) {
if( j == 8 || j == 12 || j == 16 || j == 20)
result = result + '-';
i = Math.floor(Math.random()*16).toString(16).toUpperCase();
result = result + i;
}
return result;
}
There are other methods that involve using an ActiveX control, but stay away from these!
I thought it was worth pointing out that no GUID generator can guarantee unique keys (check the Wikipedia article). There is always a chance of collisions. A GUID simply offers a large enough universe of keys to reduce the change of collisions to almost nil.
Here is a combination of the top voted answer, with a workaround for Chrome's collisions:
generateGUID = (typeof(window.crypto) != 'undefined' &&
typeof(window.crypto.getRandomValues) != 'undefined') ?
function() {
// If we have a cryptographically secure PRNG, use that
// https://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
var buf = new Uint16Array(8);
window.crypto.getRandomValues(buf);
var S4 = function(num) {
var ret = num.toString(16);
while(ret.length < 4){
ret = "0"+ret;
}
return ret;
};
return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
}
:
function() {
// Otherwise, just use Math.random
// https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
};
It is on jsbin if you want to test it.
Here's a solution dated Oct. 9, 2011 from a comment by user jed at https://gist.github.com/982883:
UUIDv4 = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}
This accomplishes the same goal as the current highest-rated answer, but in 50+ fewer bytes by exploiting coercion, recursion, and exponential notation. For those curious how it works, here's the annotated form of an older version of the function:
UUIDv4 =
function b(
a // placeholder
){
return a // if the placeholder was passed, return
? ( // a random number from 0 to 15
a ^ // unless b is 8,
Math.random() // in which case
* 16 // a random number from
>> a/4 // 8 to 11
).toString(16) // in hexadecimal
: ( // or otherwise a concatenated string:
[1e7] + // 10000000 +
-1e3 + // -1000 +
-4e3 + // -4000 +
-8e3 + // -80000000 +
-1e11 // -100000000000,
).replace( // replacing
/[018]/g, // zeroes, ones, and eights with
b // random hex digits
)
}
You can use node-uuid. It provides simple, fast generation of RFC4122 UUIDS.
Features:
Generate RFC4122 version 1 or version 4 UUIDs
Runs in Node.js and browsers.
Cryptographically strong random # generation on supporting platforms.
Small footprint (Want something smaller? Check this out!)
Install Using NPM:
npm install uuid
Or using uuid via a browser:
Download Raw File (uuid v1): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js
Download Raw File (uuid v4): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v4.js
Want even smaller? Check this out: https://gist.github.com/jed/982883
Usage:
// Generate a v1 UUID (time-based)
const uuidV1 = require('uuid/v1');
uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
// Generate a v4 UUID (random)
const uuidV4 = require('uuid/v4');
uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
// Generate a v5 UUID (namespace)
const uuidV5 = require('uuid/v5');
// ... using predefined DNS namespace (for domain names)
uuidV5('hello.example.com', v5.DNS)); // -> 'fdda765f-fc57-5604-a269-52a7df8164ec'
// ... using predefined URL namespace (for, well, URLs)
uuidV5('http://example.com/hello', v5.URL); // -> '3bbcee75-cecc-5b56-8031-b6641c1ed1f1'
// ... using a custom namespace
const MY_NAMESPACE = '(previously generated unique uuid string)';
uuidV5('hello', MY_NAMESPACE); // -> '90123e1c-7512-523e-bb28-76fab9f2f73d'
ECMAScript 2015 (ES6):
import uuid from 'uuid/v4';
const id = uuid();
var uuid = function() {
var buf = new Uint32Array(4);
window.crypto.getRandomValues(buf);
var idx = -1;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
idx++;
var r = (buf[idx>>3] >> ((idx%8)*4))&15;
var v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
};
This version is based on Briguy37's answer and some bitwise operators to extract nibble sized windows from the buffer.
It should adhere to the RFC Type 4 (random) schema, since I had problems last time parsing non-compliant UUIDs with Java's UUID.
This creates a version 4 UUID (created from pseudo random numbers):
function uuid()
{
var chars = '0123456789abcdef'.split('');
var uuid = [], rnd = Math.random, r;
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4'; // version 4
for (var i = 0; i < 36; i++)
{
if (!uuid[i])
{
r = 0 | rnd()*16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
}
}
return uuid.join('');
}
Here is a sample of the UUIDs generated:
682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
One line solution using Blobs.
window.URL.createObjectURL(new Blob([])).substring(31);
The value at the end (31) depends on the length of the URL.
EDIT:
A more compact and universal solution, as suggested by rinogo:
URL.createObjectURL(new Blob([])).substr(-36);
Simple JavaScript module as a combination of best answers in this question.
var crypto = window.crypto || window.msCrypto || null; // IE11 fix
var Guid = Guid || (function() {
var EMPTY = '00000000-0000-0000-0000-000000000000';
var _padLeft = function(paddingString, width, replacementChar) {
return paddingString.length >= width ? paddingString : _padLeft(replacementChar + paddingString, width, replacementChar || ' ');
};
var _s4 = function(number) {
var hexadecimalResult = number.toString(16);
return _padLeft(hexadecimalResult, 4, '0');
};
var _cryptoGuid = function() {
var buffer = new window.Uint16Array(8);
crypto.getRandomValues(buffer);
return [_s4(buffer[0]) + _s4(buffer[1]), _s4(buffer[2]), _s4(buffer[3]), _s4(buffer[4]), _s4(buffer[5]) + _s4(buffer[6]) + _s4(buffer[7])].join('-');
};
var _guid = function() {
var currentDateMilliseconds = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(currentChar) {
var randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0;
currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16);
return (currentChar === 'x' ? randomChar : (randomChar & 0x7 | 0x8)).toString(16);
});
};
var create = function() {
var hasCrypto = crypto != 'undefined' && crypto !== null,
hasRandomValues = typeof(window.crypto.getRandomValues) != 'undefined';
return (hasCrypto && hasRandomValues) ? _cryptoGuid() : _guid();
};
return {
newGuid: create,
empty: EMPTY
};
})();
// DEMO: Create and show GUID
console.log('1. New Guid: ' + Guid.newGuid());
// DEMO: Show empty GUID
console.log('2. Empty Guid: ' + Guid.empty);
Usage:
Guid.newGuid()
"c6c2d12f-d76b-5739-e551-07e6de5b0807"
Guid.empty
"00000000-0000-0000-0000-000000000000"
The version below is an adaptation of broofa's answer, but updated to include a "true" random function that uses crypto libraries where available, and the Alea() function as a fallback.
Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); }
Math.trueRandom = (function() {
var crypt = window.crypto || window.msCrypto;
if (crypt && crypt.getRandomValues) {
// If we have a crypto library, use it
var random = function(min, max) {
var rval = 0;
var range = max - min;
if (range < 2) {
return min;
}
var bits_needed = Math.ceil(Math.log2(range));
if (bits_needed > 53) {
throw new Exception("We cannot generate numbers larger than 53 bits.");
}
var bytes_needed = Math.ceil(bits_needed / 8);
var mask = Math.pow(2, bits_needed) - 1;
// 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111
// Create byte array and fill with N random numbers
var byteArray = new Uint8Array(bytes_needed);
crypt.getRandomValues(byteArray);
var p = (bytes_needed - 1) * 8;
for(var i = 0; i < bytes_needed; i++ ) {
rval += byteArray[i] * Math.pow(2, p);
p -= 8;
}
// Use & to apply the mask and reduce the number of recursive lookups
rval = rval & mask;
if (rval >= range) {
// Integer out of acceptable range
return random(min, max);
}
// Return an integer that falls within the range
return min + rval;
}
return function() {
var r = random(0, 1000000000) / 1000000000;
return r;
};
} else {
// From https://web.archive.org/web/20120502223108/http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagøe <baagoe#baagoe.com>, 2010
function Mash() {
var n = 0xefc8249d;
var mash = function(data) {
data = data.toString();
for (var i = 0; i < data.length; i++) {
n += data.charCodeAt(i);
var h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000; // 2^32
}
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
};
mash.version = 'Mash 0.9';
return mash;
}
// From http://baagoe.com/en/RandomMusings/javascript/
function Alea() {
return (function(args) {
// Johannes Baagøe <baagoe#baagoe.com>, 2010
var s0 = 0;
var s1 = 0;
var s2 = 0;
var c = 1;
if (args.length == 0) {
args = [+new Date()];
}
var mash = Mash();
s0 = mash(' ');
s1 = mash(' ');
s2 = mash(' ');
for (var i = 0; i < args.length; i++) {
s0 -= mash(args[i]);
if (s0 < 0) {
s0 += 1;
}
s1 -= mash(args[i]);
if (s1 < 0) {
s1 += 1;
}
s2 -= mash(args[i]);
if (s2 < 0) {
s2 += 1;
}
}
mash = null;
var random = function() {
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
s0 = s1;
s1 = s2;
return s2 = t - (c = t | 0);
};
random.uint32 = function() {
return random() * 0x100000000; // 2^32
};
random.fract53 = function() {
return random() +
(random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
};
random.version = 'Alea 0.9';
random.args = args;
return random;
}(Array.prototype.slice.call(arguments)));
};
return Alea();
}
}());
Math.guid = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.trueRandom() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
JavaScript project on GitHub - https://github.com/LiosK/UUID.js
UUID.js The RFC-compliant UUID generator for JavaScript.
See RFC 4122 http://www.ietf.org/rfc/rfc4122.txt.
Features Generates RFC 4122 compliant UUIDs.
Version 4 UUIDs (UUIDs from random numbers) and version 1 UUIDs
(time-based UUIDs) are available.
UUID object allows a variety of access to the UUID including access to
the UUID fields.
Low timestamp resolution of JavaScript is compensated by random
numbers.
// RFC 4122
//
// A UUID is 128 bits long
//
// String representation is five fields of 4, 2, 2, 2, and 6 bytes.
// Fields represented as lowercase, zero-filled, hexadecimal strings, and
// are separated by dash characters
//
// A version 4 UUID is generated by setting all but six bits to randomly
// chosen values
var uuid = [
Math.random().toString(16).slice(2, 10),
Math.random().toString(16).slice(2, 6),
// Set the four most significant bits (bits 12 through 15) of the
// time_hi_and_version field to the 4-bit version number from Section
// 4.1.3
(Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),
// Set the two most significant bits (bits 6 and 7) of the
// clock_seq_hi_and_reserved to zero and one, respectively
(Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),
Math.random().toString(16).slice(2, 14)].join('-');
Added in: v15.6.0, v14.17.0 there is a built-in crypto.randomUUID() function.
import * as crypto from "crypto";
const uuid = crypto.randomUUID();
In the browser, crypto.randomUUID() is currently supported in Chromium 92+ and Firefox 95+.
For those wanting an RFC 4122 version 4 compliant solution with speed considerations (few calls to Math.random()):
var rand = Math.random;
function UUID() {
var nbr, randStr = "";
do {
randStr += (nbr = rand()).toString(16).substr(3, 6);
} while (randStr.length < 30);
return (
randStr.substr(0, 8) + "-" +
randStr.substr(8, 4) + "-4" +
randStr.substr(12, 3) + "-" +
((nbr*4|0)+8).toString(16) + // [89ab]
randStr.substr(15, 3) + "-" +
randStr.substr(18, 12)
);
}
console.log( UUID() );
The above function should have a decent balance between speed and randomness.
I wanted to understand broofa's answer, so I expanded it and added comments:
var uuid = function () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function (match) {
/*
* Create a random nibble. The two clever bits of this code:
*
* - Bitwise operations will truncate floating point numbers
* - For a bitwise OR of any x, x | 0 = x
*
* So:
*
* Math.random * 16
*
* creates a random floating point number
* between 0 (inclusive) and 16 (exclusive) and
*
* | 0
*
* truncates the floating point number into an integer.
*/
var randomNibble = Math.random() * 16 | 0;
/*
* Resolves the variant field. If the variant field (delineated
* as y in the initial string) is matched, the nibble must
* match the mask (where x is a do-not-care bit):
*
* 10xx
*
* This is achieved by performing the following operations in
* sequence (where x is an intermediate result):
*
* - x & 0x3, which is equivalent to x % 3
* - x | 0x8, which is equivalent to x + 8
*
* This results in a nibble between 8 inclusive and 11 exclusive,
* (or 1000 and 1011 in binary), all of which satisfy the variant
* field mask above.
*/
var nibble = (match == 'y') ?
(randomNibble & 0x3 | 0x8) :
randomNibble;
/*
* Ensure the nibble integer is encoded as base 16 (hexadecimal).
*/
return nibble.toString(16);
}
);
};
ES6 sample
const guid=()=> {
const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}
I adjusted my own UUID/GUID generator with some extras here.
I'm using the following Kybos random number generator to be a bit more cryptographically sound.
Below is my script with the Mash and Kybos methods from baagoe.com excluded.
//UUID/Guid Generator
// use: UUID.create() or UUID.createSequential()
// convenience: UUID.empty, UUID.tryParse(string)
(function(w){
// From http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagøe <baagoe#baagoe.com>, 2010
//function Mash() {...};
// From http://baagoe.com/en/RandomMusings/javascript/
//function Kybos() {...};
var rnd = Kybos();
//UUID/GUID Implementation from http://frugalcoder.us/post/2012/01/13/javascript-guid-uuid-generator.aspx
var UUID = {
"empty": "00000000-0000-0000-0000-000000000000"
,"parse": function(input) {
var ret = input.toString().trim().toLowerCase().replace(/^[\s\r\n]+|[\{\}]|[\s\r\n]+$/g, "");
if ((/[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}/).test(ret))
return ret;
else
throw new Error("Unable to parse UUID");
}
,"createSequential": function() {
var ret = new Date().valueOf().toString(16).replace("-","")
for (;ret.length < 12; ret = "0" + ret);
ret = ret.substr(ret.length-12,12); //only least significant part
for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-");
}
,"create": function() {
var ret = "";
for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-");
}
,"random": function() {
return rnd();
}
,"tryParse": function(input) {
try {
return UUID.parse(input);
} catch(ex) {
return UUID.empty;
}
}
};
UUID["new"] = UUID.create;
w.UUID = w.Guid = UUID;
}(window || this));
The native URL.createObjectURL is generating an UUID. You can take advantage of this.
function uuid() {
const url = URL.createObjectURL(new Blob())
const [id] = url.toString().split('/').reverse()
URL.revokeObjectURL(url)
return id
}
The better way:
function(
a, b // Placeholders
){
for( // Loop :)
b = a = ''; // b - result , a - numeric variable
a++ < 36; //
b += a*51&52 // If "a" is not 9 or 14 or 19 or 24
? // return a random number or 4
(
a^15 // If "a" is not 15,
? // generate a random number from 0 to 15
8^Math.random() *
(a^20 ? 16 : 4) // unless "a" is 20, in which case a random number from 8 to 11,
:
4 // otherwise 4
).toString(16)
:
'-' // In other cases, (if "a" is 9,14,19,24) insert "-"
);
return b
}
Minimized:
function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b}
The following is simple code that uses crypto.getRandomValues(a) on supported browsers (Internet Explorer 11+, iOS 7+, Firefox 21+, Chrome, and Android Chrome).
It avoids using Math.random(), because that can cause collisions (for example 20 collisions for 4000 generated UUIDs in a real situation by Muxa).
function uuid() {
function randomDigit() {
if (crypto && crypto.getRandomValues) {
var rands = new Uint8Array(1);
crypto.getRandomValues(rands);
return (rands[0] % 16).toString(16);
} else {
return ((Math.random() * 16) | 0).toString(16);
}
}
var crypto = window.crypto || window.msCrypto;
return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit);
}
Notes:
Optimised for code readability, not speed, so it is suitable for, say, a few hundred UUIDs per second. It generates about 10000 uuid() per second in Chromium on my laptop using http://jsbin.com/fuwigo/1 to measure performance.
It only uses 8 for "y" because that simplifies code readability (y is allowed to be 8, 9, A, or B).
If you just need a random 128 bit string in no particular format, you can use:
function uuid() {
return crypto.getRandomValues(new Uint32Array(4)).join('-');
}
Which will return something like 2350143528-4164020887-938913176-2513998651.
I couldn't find any answer that uses a single 16-octet TypedArray and a DataView, so I think the following solution for generating a version 4 UUID per the RFC will stand on its own here:
const uuid4 = () => {
const ho = (n, p) => n.toString(16).padStart(p, 0); /// Return the hexadecimal text representation of number `n`, padded with zeroes to be of length `p`
const data = crypto.getRandomValues(new Uint8Array(16)); /// Fill the buffer with random data
data[6] = (data[6] & 0xf) | 0x40; /// Patch the 6th byte to reflect a version 4 UUID
data[8] = (data[8] & 0x3f) | 0x80; /// Patch the 8th byte to reflect a variant 1 UUID (version 4 UUIDs are)
const view = new DataView(data.buffer); /// Create a view backed by a 16-byte buffer
return `${ho(view.getUint32(0), 8)}-${ho(view.getUint16(4), 4)}-${ho(view.getUint16(6), 4)}-${ho(view.getUint16(8), 4)}-${ho(view.getUint32(10), 8)}${ho(view.getUint16(14), 4)}`; /// Compile the canonical textual form from the array data
};
I prefer it because:
it only relies on functions available to the standard ECMAScript platform, where possible -- which is all but one procedure
it only uses a single buffer, minimizing copying of data, which should in theory yield performance advantages
At the time of writing this, getRandomValues is not something implemented for the crypto object in Node.js. However, it has the equivalent randomBytes function which may be used instead.
Just another more readable variant with just two mutations.
function uuid4()
{
function hex (s, b)
{
return s +
(b >>> 4 ).toString (16) + // high nibble
(b & 0b1111).toString (16); // low nibble
}
let r = crypto.getRandomValues (new Uint8Array (16));
r[6] = r[6] >>> 4 | 0b01000000; // Set type 4: 0100
r[8] = r[8] >>> 3 | 0b10000000; // Set variant: 100
return r.slice ( 0, 4).reduce (hex, '' ) +
r.slice ( 4, 6).reduce (hex, '-') +
r.slice ( 6, 8).reduce (hex, '-') +
r.slice ( 8, 10).reduce (hex, '-') +
r.slice (10, 16).reduce (hex, '-');
}

Is there a way to create a unique ID using Node.js without additional modules? [duplicate]

How do I create GUIDs (globally-unique identifiers) in JavaScript? The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.
I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc.
[Edited 2021-10-16 to reflect latest best-practices for producing RFC4122-compliant UUIDs]
Most readers here will want to use the uuid module. It is well-tested and supported.
The crypto.randomUUID() function is an emerging standard that is supported in Node.js and an increasing number of browsers. However because new browser APIs are restricted to secure contexts this method is only available to pages served locally (localhost or 127.0.0.1) or over HTTPS. If you're interested in seeing this restriction lifted for crypto.randomUUID() you can follow this GitHub issue.
If neither of those work for you, there is this method (based on the original answer to this question):
function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
console.log(uuidv4());
Note: The use of any UUID generator that relies on Math.random() is strongly discouraged (including snippets featured in previous versions of this answer) for reasons best explained here. TL;DR: solutions based on Math.random() do not provide good uniqueness guarantees.
UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier), according to RFC 4122, are identifiers designed to provide certain uniqueness guarantees.
While it is possible to implement RFC-compliant UUIDs in a few lines of JavaScript code (e.g., see #broofa's answer, below) there are several common pitfalls:
Invalid id format (UUIDs must be of the form "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx", where x is one of [0-9, a-f] M is one of [1-5], and N is [8, 9, a, or b]
Use of a low-quality source of randomness (such as Math.random)
Thus, developers writing code for production environments are encouraged to use a rigorous, well-maintained implementation such as the uuid module.
I really like how clean Broofa's answer is, but it's unfortunate that poor implementations of Math.random leave the chance for collision.
Here's a similar RFC4122 version 4 compliant solution that solves that issue by offsetting the first 13 hex numbers by a hex portion of the timestamp, and once depleted offsets by a hex portion of the microseconds since pageload. That way, even if Math.random is on the same seed, both clients would have to generate the UUID the exact same number of microseconds since pageload (if high-perfomance time is supported) AND at the exact same millisecond (or 10,000+ years later) to get the same UUID:
function generateUUID() { // Public Domain/MIT
var d = new Date().getTime();//Timestamp
var d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16;//random number between 0 and 16
if(d > 0){//Use timestamp until depleted
r = (d + r)%16 | 0;
d = Math.floor(d/16);
} else {//Use microseconds since page-load if supported
r = (d2 + r)%16 | 0;
d2 = Math.floor(d2/16);
}
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
var onClick = function(){
document.getElementById('uuid').textContent = generateUUID();
}
onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID" onclick="onClick();">Generate UUID</button>
Here's a fiddle to test.
Modernized snippet for ES6
const generateUUID = () => {
let
d = new Date().getTime(),
d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
let r = Math.random() * 16;
if (d > 0) {
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
});
};
const onClick = (e) => document.getElementById('uuid').textContent = generateUUID();
document.getElementById('generateUUID').addEventListener('click', onClick);
onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID">Generate UUID</button>
broofa's answer is pretty slick, indeed - impressively clever, really... RFC4122 compliant, somewhat readable, and compact. Awesome!
But if you're looking at that regular expression, those many replace() callbacks, toString()'s and Math.random() function calls (where he's only using four bits of the result and wasting the rest), you may start to wonder about performance. Indeed, joelpt even decided to toss out an RFC for generic GUID speed with generateQuickGUID.
But, can we get speed and RFC compliance? I say, YES! Can we maintain readability? Well... Not really, but it's easy if you follow along.
But first, my results, compared to broofa, guid (the accepted answer), and the non-rfc-compliant generateQuickGuid:
Desktop Android
broofa: 1617ms 12869ms
e1: 636ms 5778ms
e2: 606ms 4754ms
e3: 364ms 3003ms
e4: 329ms 2015ms
e5: 147ms 1156ms
e6: 146ms 1035ms
e7: 105ms 726ms
guid: 962ms 10762ms
generateQuickGuid: 292ms 2961ms
- Note: 500k iterations, results will vary by browser/CPU.
So by my 6th iteration of optimizations, I beat the most popular answer by over 12 times, the accepted answer by over 9 times, and the fast-non-compliant answer by 2-3 times. And I'm still RFC 4122 compliant.
Interested in how? I've put the full source on http://jsfiddle.net/jcward/7hyaC/3/ and on https://jsben.ch/xczxS
For an explanation, let's start with broofa's code:
function broofa() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
console.log(broofa())
So it replaces x with any random hexadecimal digit, y with random data (except forcing the top two bits to 10 per the RFC spec), and the regex doesn't match the - or 4 characters, so he doesn't have to deal with them. Very, very slick.
The first thing to know is that function calls are expensive, as are regular expressions (though he only uses 1, it has 32 callbacks, one for each match, and in each of the 32 callbacks it calls Math.random() and v.toString(16)).
The first step toward performance is to eliminate the RegEx and its callback functions and use a simple loop instead. This means we have to deal with the - and 4 characters whereas broofa did not. Also, note that we can use String Array indexing to keep his slick String template architecture:
function e1() {
var u='',i=0;
while(i++<36) {
var c='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'[i-1],r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:v.toString(16)
}
return u;
}
console.log(e1())
Basically, the same inner logic, except we check for - or 4, and using a while loop (instead of replace() callbacks) gets us an almost 3X improvement!
The next step is a small one on the desktop but makes a decent difference on mobile. Let's make fewer Math.random() calls and utilize all those random bits instead of throwing 87% of them away with a random buffer that gets shifted out each iteration. Let's also move that template definition out of the loop, just in case it helps:
function e2() {
var u='',m='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',i=0,rb=Math.random()*0xffffffff|0;
while(i++<36) {
var c=m[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:v.toString(16);rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
}
return u
}
console.log(e2())
This saves us 10-30% depending on platform. Not bad. But the next big step gets rid of the toString function calls altogether with an optimization classic - the look-up table. A simple 16-element lookup table will perform the job of toString(16) in much less time:
function e3() {
var h='0123456789abcdef';
var k='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
/* same as e4() below */
}
function e4() {
var h=['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
var k=['x','x','x','x','x','x','x','x','-','x','x','x','x','-','4','x','x','x','-','y','x','x','x','-','x','x','x','x','x','x','x','x','x','x','x','x'];
var u='',i=0,rb=Math.random()*0xffffffff|0;
while(i++<36) {
var c=k[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:h[v];rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
}
return u
}
console.log(e4())
The next optimization is another classic. Since we're only handling four bits of output in each loop iteration, let's cut the number of loops in half and process eight bits in each iteration. This is tricky since we still have to handle the RFC compliant bit positions, but it's not too hard. We then have to make a larger lookup table (16x16, or 256) to store 0x00 - 0xFF, and we build it only once, outside the e5() function.
var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e5() {
var k=['x','x','x','x','-','x','x','-','4','x','-','y','x','-','x','x','x','x','x','x'];
var u='',i=0,rb=Math.random()*0xffffffff|0;
while(i++<20) {
var c=k[i-1],r=rb&0xff,v=c=='x'?r:(c=='y'?(r&0x3f|0x80):(r&0xf|0x40));
u+=(c=='-')?c:lut[v];rb=i%4==0?Math.random()*0xffffffff|0:rb>>8
}
return u
}
console.log(e5())
I tried an e6() that processes 16-bits at a time, still using the 256-element LUT, and it showed the diminishing returns of optimization. Though it had fewer iterations, the inner logic was complicated by the increased processing, and it performed the same on desktop, and only ~10% faster on mobile.
The final optimization technique to apply - unroll the loop. Since we're looping a fixed number of times, we can technically write this all out by hand. I tried this once with a single random variable, r, that I kept reassigning, and performance tanked. But with four variables assigned random data up front, then using the lookup table, and applying the proper RFC bits, this version smokes them all:
var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e7()
{
var d0 = Math.random()*0xffffffff|0;
var d1 = Math.random()*0xffffffff|0;
var d2 = Math.random()*0xffffffff|0;
var d3 = Math.random()*0xffffffff|0;
return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+
lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+
lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+
lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff];
}
console.log(e7())
Modualized: http://jcward.com/UUID.js - UUID.generate()
The funny thing is, generating 16 bytes of random data is the easy part. The whole trick is expressing it in string format with RFC compliance, and it's most tightly accomplished with 16 bytes of random data, an unrolled loop and lookup table.
I hope my logic is correct -- it's very easy to make a mistake in this kind of tedious bit work. But the outputs look good to me. I hope you enjoyed this mad ride through code optimization!
Be advised: my primary goal was to show and teach potential optimization strategies. Other answers cover important topics such as collisions and truly random numbers, which are important for generating good UUIDs.
Use:
let uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);
document.getElementById("unique").innerHTML =
Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
<div id="unique">
</div>
If IDs are generated more than 1 millisecond apart, they are 100% unique.
If two IDs are generated at shorter intervals, and assuming that the random method is truly random, this would generate IDs that are 99.99999999999999% likely to be globally unique (collision in 1 of 10^15).
You can increase this number by adding more digits, but to generate 100% unique IDs you will need to use a global counter.
If you need RFC compatibility, this formatting will pass as a valid version 4 GUID:
let u = Date.now().toString(16) + Math.random().toString(16) + '0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');
let u = Date.now().toString(16)+Math.random().toString(16)+'0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');
document.getElementById("unique").innerHTML = guid;
<div id="unique">
</div>
The above code follow the intention, but not the letter of the RFC. Among other discrepancies it's a few random digits short. (Add more random digits if you need it) The upside is that this is really fast :)
You can test validity of your GUID here
Here's some code based on RFC 4122, section 4.4 (Algorithms for Creating a UUID from Truly Random or Pseudo-Random Number).
function createUUID() {
// http://www.ietf.org/rfc/rfc4122.txt
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
}
This is the fastest GUID-like string generator method in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. It does not generate a standard-compliant GUID.
Ten million executions of this implementation take just 32.5 seconds, which is the fastest I've ever seen in a browser (the only solution without loops/iterations).
The function is as simple as:
/**
* Generates a GUID string.
* #returns {string} The generated GUID.
* #example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
* #author Slavik Meltser.
* #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 "000000000" (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 for 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"+"000000000"), and then cutting it off from the second index (third 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 four pieces, each piece divided into two types (or formats): XXXXXXXX and -XXXX-XXXX.
Now I'm building the GUID using these two types to assemble the GUID with call four 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.
Link to this post on my blog
Enjoy! :-)
Here is a totally non-compliant but very performant implementation to generate an ASCII-safe GUID-like unique identifier.
function generateQuickGuid() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
Generates 26 [a-z0-9] characters, yielding a UID that is both shorter and more unique than RFC compliant GUIDs. Dashes can be trivially added if human-readability matters.
Here are usage examples and timings for this function and several of this question's other answers. The timing was performed under Chrome m25, 10 million iterations each.
>>> generateQuickGuid()
"nvcjf1hs7tf8yyk4lmlijqkuo9"
"yq6gipxqta4kui8z05tgh9qeel"
"36dh5sec7zdj90sk2rx7pjswi2"
runtime: 32.5s
>>> GUID() // John Millikin
"7a342ca2-e79f-528e-6302-8f901b0b6888"
runtime: 57.8s
>>> regexGuid() // broofa
"396e0c46-09e4-4b19-97db-bd423774a4b3"
runtime: 91.2s
>>> createUUID() // Kevin Hakanson
"403aa1ab-9f70-44ec-bc08-5d5ac56bd8a5"
runtime: 65.9s
>>> UUIDv4() // Jed Schmidt
"f4d7d31f-fa83-431a-b30c-3e6cc37cc6ee"
runtime: 282.4s
>>> Math.uuid() // broofa
"5BD52F55-E68F-40FC-93C2-90EE069CE545"
runtime: 225.8s
>>> Math.uuidFast() // broofa
"6CB97A68-23A2-473E-B75B-11263781BBE6"
runtime: 92.0s
>>> Math.uuidCompact() // broofa
"3d7b7a06-0a67-4b67-825c-e5c43ff8c1e8"
runtime: 229.0s
>>> bitwiseGUID() // jablko
"baeaa2f-7587-4ff1-af23-eeab3e92"
runtime: 79.6s
>>>> betterWayGUID() // Andrea Turri
"383585b0-9753-498d-99c3-416582e9662c"
runtime: 60.0s
>>>> UUID() // John Fowler
"855f997b-4369-4cdb-b7c9-7142ceaf39e8"
runtime: 62.2s
Here is the timing code.
var r;
console.time('t');
for (var i = 0; i < 10000000; i++) {
r = FuncToTest();
};
console.timeEnd('t');
From sagi shkedy's technical blog:
function generateGuid() {
var result, i, j;
result = '';
for(j=0; j<32; j++) {
if( j == 8 || j == 12 || j == 16 || j == 20)
result = result + '-';
i = Math.floor(Math.random()*16).toString(16).toUpperCase();
result = result + i;
}
return result;
}
There are other methods that involve using an ActiveX control, but stay away from these!
I thought it was worth pointing out that no GUID generator can guarantee unique keys (check the Wikipedia article). There is always a chance of collisions. A GUID simply offers a large enough universe of keys to reduce the change of collisions to almost nil.
Here is a combination of the top voted answer, with a workaround for Chrome's collisions:
generateGUID = (typeof(window.crypto) != 'undefined' &&
typeof(window.crypto.getRandomValues) != 'undefined') ?
function() {
// If we have a cryptographically secure PRNG, use that
// https://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
var buf = new Uint16Array(8);
window.crypto.getRandomValues(buf);
var S4 = function(num) {
var ret = num.toString(16);
while(ret.length < 4){
ret = "0"+ret;
}
return ret;
};
return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
}
:
function() {
// Otherwise, just use Math.random
// https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
};
It is on jsbin if you want to test it.
Here's a solution dated Oct. 9, 2011 from a comment by user jed at https://gist.github.com/982883:
UUIDv4 = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}
This accomplishes the same goal as the current highest-rated answer, but in 50+ fewer bytes by exploiting coercion, recursion, and exponential notation. For those curious how it works, here's the annotated form of an older version of the function:
UUIDv4 =
function b(
a // placeholder
){
return a // if the placeholder was passed, return
? ( // a random number from 0 to 15
a ^ // unless b is 8,
Math.random() // in which case
* 16 // a random number from
>> a/4 // 8 to 11
).toString(16) // in hexadecimal
: ( // or otherwise a concatenated string:
[1e7] + // 10000000 +
-1e3 + // -1000 +
-4e3 + // -4000 +
-8e3 + // -80000000 +
-1e11 // -100000000000,
).replace( // replacing
/[018]/g, // zeroes, ones, and eights with
b // random hex digits
)
}
You can use node-uuid. It provides simple, fast generation of RFC4122 UUIDS.
Features:
Generate RFC4122 version 1 or version 4 UUIDs
Runs in Node.js and browsers.
Cryptographically strong random # generation on supporting platforms.
Small footprint (Want something smaller? Check this out!)
Install Using NPM:
npm install uuid
Or using uuid via a browser:
Download Raw File (uuid v1): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js
Download Raw File (uuid v4): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v4.js
Want even smaller? Check this out: https://gist.github.com/jed/982883
Usage:
// Generate a v1 UUID (time-based)
const uuidV1 = require('uuid/v1');
uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
// Generate a v4 UUID (random)
const uuidV4 = require('uuid/v4');
uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
// Generate a v5 UUID (namespace)
const uuidV5 = require('uuid/v5');
// ... using predefined DNS namespace (for domain names)
uuidV5('hello.example.com', v5.DNS)); // -> 'fdda765f-fc57-5604-a269-52a7df8164ec'
// ... using predefined URL namespace (for, well, URLs)
uuidV5('http://example.com/hello', v5.URL); // -> '3bbcee75-cecc-5b56-8031-b6641c1ed1f1'
// ... using a custom namespace
const MY_NAMESPACE = '(previously generated unique uuid string)';
uuidV5('hello', MY_NAMESPACE); // -> '90123e1c-7512-523e-bb28-76fab9f2f73d'
ECMAScript 2015 (ES6):
import uuid from 'uuid/v4';
const id = uuid();
var uuid = function() {
var buf = new Uint32Array(4);
window.crypto.getRandomValues(buf);
var idx = -1;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
idx++;
var r = (buf[idx>>3] >> ((idx%8)*4))&15;
var v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
};
This version is based on Briguy37's answer and some bitwise operators to extract nibble sized windows from the buffer.
It should adhere to the RFC Type 4 (random) schema, since I had problems last time parsing non-compliant UUIDs with Java's UUID.
This creates a version 4 UUID (created from pseudo random numbers):
function uuid()
{
var chars = '0123456789abcdef'.split('');
var uuid = [], rnd = Math.random, r;
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4'; // version 4
for (var i = 0; i < 36; i++)
{
if (!uuid[i])
{
r = 0 | rnd()*16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
}
}
return uuid.join('');
}
Here is a sample of the UUIDs generated:
682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
One line solution using Blobs.
window.URL.createObjectURL(new Blob([])).substring(31);
The value at the end (31) depends on the length of the URL.
EDIT:
A more compact and universal solution, as suggested by rinogo:
URL.createObjectURL(new Blob([])).substr(-36);
Simple JavaScript module as a combination of best answers in this question.
var crypto = window.crypto || window.msCrypto || null; // IE11 fix
var Guid = Guid || (function() {
var EMPTY = '00000000-0000-0000-0000-000000000000';
var _padLeft = function(paddingString, width, replacementChar) {
return paddingString.length >= width ? paddingString : _padLeft(replacementChar + paddingString, width, replacementChar || ' ');
};
var _s4 = function(number) {
var hexadecimalResult = number.toString(16);
return _padLeft(hexadecimalResult, 4, '0');
};
var _cryptoGuid = function() {
var buffer = new window.Uint16Array(8);
crypto.getRandomValues(buffer);
return [_s4(buffer[0]) + _s4(buffer[1]), _s4(buffer[2]), _s4(buffer[3]), _s4(buffer[4]), _s4(buffer[5]) + _s4(buffer[6]) + _s4(buffer[7])].join('-');
};
var _guid = function() {
var currentDateMilliseconds = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(currentChar) {
var randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0;
currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16);
return (currentChar === 'x' ? randomChar : (randomChar & 0x7 | 0x8)).toString(16);
});
};
var create = function() {
var hasCrypto = crypto != 'undefined' && crypto !== null,
hasRandomValues = typeof(window.crypto.getRandomValues) != 'undefined';
return (hasCrypto && hasRandomValues) ? _cryptoGuid() : _guid();
};
return {
newGuid: create,
empty: EMPTY
};
})();
// DEMO: Create and show GUID
console.log('1. New Guid: ' + Guid.newGuid());
// DEMO: Show empty GUID
console.log('2. Empty Guid: ' + Guid.empty);
Usage:
Guid.newGuid()
"c6c2d12f-d76b-5739-e551-07e6de5b0807"
Guid.empty
"00000000-0000-0000-0000-000000000000"
The version below is an adaptation of broofa's answer, but updated to include a "true" random function that uses crypto libraries where available, and the Alea() function as a fallback.
Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); }
Math.trueRandom = (function() {
var crypt = window.crypto || window.msCrypto;
if (crypt && crypt.getRandomValues) {
// If we have a crypto library, use it
var random = function(min, max) {
var rval = 0;
var range = max - min;
if (range < 2) {
return min;
}
var bits_needed = Math.ceil(Math.log2(range));
if (bits_needed > 53) {
throw new Exception("We cannot generate numbers larger than 53 bits.");
}
var bytes_needed = Math.ceil(bits_needed / 8);
var mask = Math.pow(2, bits_needed) - 1;
// 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111
// Create byte array and fill with N random numbers
var byteArray = new Uint8Array(bytes_needed);
crypt.getRandomValues(byteArray);
var p = (bytes_needed - 1) * 8;
for(var i = 0; i < bytes_needed; i++ ) {
rval += byteArray[i] * Math.pow(2, p);
p -= 8;
}
// Use & to apply the mask and reduce the number of recursive lookups
rval = rval & mask;
if (rval >= range) {
// Integer out of acceptable range
return random(min, max);
}
// Return an integer that falls within the range
return min + rval;
}
return function() {
var r = random(0, 1000000000) / 1000000000;
return r;
};
} else {
// From https://web.archive.org/web/20120502223108/http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagøe <baagoe#baagoe.com>, 2010
function Mash() {
var n = 0xefc8249d;
var mash = function(data) {
data = data.toString();
for (var i = 0; i < data.length; i++) {
n += data.charCodeAt(i);
var h = 0.02519603282416938 * n;
n = h >>> 0;
h -= n;
h *= n;
n = h >>> 0;
h -= n;
n += h * 0x100000000; // 2^32
}
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
};
mash.version = 'Mash 0.9';
return mash;
}
// From http://baagoe.com/en/RandomMusings/javascript/
function Alea() {
return (function(args) {
// Johannes Baagøe <baagoe#baagoe.com>, 2010
var s0 = 0;
var s1 = 0;
var s2 = 0;
var c = 1;
if (args.length == 0) {
args = [+new Date()];
}
var mash = Mash();
s0 = mash(' ');
s1 = mash(' ');
s2 = mash(' ');
for (var i = 0; i < args.length; i++) {
s0 -= mash(args[i]);
if (s0 < 0) {
s0 += 1;
}
s1 -= mash(args[i]);
if (s1 < 0) {
s1 += 1;
}
s2 -= mash(args[i]);
if (s2 < 0) {
s2 += 1;
}
}
mash = null;
var random = function() {
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
s0 = s1;
s1 = s2;
return s2 = t - (c = t | 0);
};
random.uint32 = function() {
return random() * 0x100000000; // 2^32
};
random.fract53 = function() {
return random() +
(random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
};
random.version = 'Alea 0.9';
random.args = args;
return random;
}(Array.prototype.slice.call(arguments)));
};
return Alea();
}
}());
Math.guid = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.trueRandom() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
JavaScript project on GitHub - https://github.com/LiosK/UUID.js
UUID.js The RFC-compliant UUID generator for JavaScript.
See RFC 4122 http://www.ietf.org/rfc/rfc4122.txt.
Features Generates RFC 4122 compliant UUIDs.
Version 4 UUIDs (UUIDs from random numbers) and version 1 UUIDs
(time-based UUIDs) are available.
UUID object allows a variety of access to the UUID including access to
the UUID fields.
Low timestamp resolution of JavaScript is compensated by random
numbers.
// RFC 4122
//
// A UUID is 128 bits long
//
// String representation is five fields of 4, 2, 2, 2, and 6 bytes.
// Fields represented as lowercase, zero-filled, hexadecimal strings, and
// are separated by dash characters
//
// A version 4 UUID is generated by setting all but six bits to randomly
// chosen values
var uuid = [
Math.random().toString(16).slice(2, 10),
Math.random().toString(16).slice(2, 6),
// Set the four most significant bits (bits 12 through 15) of the
// time_hi_and_version field to the 4-bit version number from Section
// 4.1.3
(Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),
// Set the two most significant bits (bits 6 and 7) of the
// clock_seq_hi_and_reserved to zero and one, respectively
(Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),
Math.random().toString(16).slice(2, 14)].join('-');
Added in: v15.6.0, v14.17.0 there is a built-in crypto.randomUUID() function.
import * as crypto from "crypto";
const uuid = crypto.randomUUID();
In the browser, crypto.randomUUID() is currently supported in Chromium 92+ and Firefox 95+.
For those wanting an RFC 4122 version 4 compliant solution with speed considerations (few calls to Math.random()):
var rand = Math.random;
function UUID() {
var nbr, randStr = "";
do {
randStr += (nbr = rand()).toString(16).substr(3, 6);
} while (randStr.length < 30);
return (
randStr.substr(0, 8) + "-" +
randStr.substr(8, 4) + "-4" +
randStr.substr(12, 3) + "-" +
((nbr*4|0)+8).toString(16) + // [89ab]
randStr.substr(15, 3) + "-" +
randStr.substr(18, 12)
);
}
console.log( UUID() );
The above function should have a decent balance between speed and randomness.
I wanted to understand broofa's answer, so I expanded it and added comments:
var uuid = function () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function (match) {
/*
* Create a random nibble. The two clever bits of this code:
*
* - Bitwise operations will truncate floating point numbers
* - For a bitwise OR of any x, x | 0 = x
*
* So:
*
* Math.random * 16
*
* creates a random floating point number
* between 0 (inclusive) and 16 (exclusive) and
*
* | 0
*
* truncates the floating point number into an integer.
*/
var randomNibble = Math.random() * 16 | 0;
/*
* Resolves the variant field. If the variant field (delineated
* as y in the initial string) is matched, the nibble must
* match the mask (where x is a do-not-care bit):
*
* 10xx
*
* This is achieved by performing the following operations in
* sequence (where x is an intermediate result):
*
* - x & 0x3, which is equivalent to x % 3
* - x | 0x8, which is equivalent to x + 8
*
* This results in a nibble between 8 inclusive and 11 exclusive,
* (or 1000 and 1011 in binary), all of which satisfy the variant
* field mask above.
*/
var nibble = (match == 'y') ?
(randomNibble & 0x3 | 0x8) :
randomNibble;
/*
* Ensure the nibble integer is encoded as base 16 (hexadecimal).
*/
return nibble.toString(16);
}
);
};
ES6 sample
const guid=()=> {
const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}
I adjusted my own UUID/GUID generator with some extras here.
I'm using the following Kybos random number generator to be a bit more cryptographically sound.
Below is my script with the Mash and Kybos methods from baagoe.com excluded.
//UUID/Guid Generator
// use: UUID.create() or UUID.createSequential()
// convenience: UUID.empty, UUID.tryParse(string)
(function(w){
// From http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagøe <baagoe#baagoe.com>, 2010
//function Mash() {...};
// From http://baagoe.com/en/RandomMusings/javascript/
//function Kybos() {...};
var rnd = Kybos();
//UUID/GUID Implementation from http://frugalcoder.us/post/2012/01/13/javascript-guid-uuid-generator.aspx
var UUID = {
"empty": "00000000-0000-0000-0000-000000000000"
,"parse": function(input) {
var ret = input.toString().trim().toLowerCase().replace(/^[\s\r\n]+|[\{\}]|[\s\r\n]+$/g, "");
if ((/[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}/).test(ret))
return ret;
else
throw new Error("Unable to parse UUID");
}
,"createSequential": function() {
var ret = new Date().valueOf().toString(16).replace("-","")
for (;ret.length < 12; ret = "0" + ret);
ret = ret.substr(ret.length-12,12); //only least significant part
for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-");
}
,"create": function() {
var ret = "";
for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-");
}
,"random": function() {
return rnd();
}
,"tryParse": function(input) {
try {
return UUID.parse(input);
} catch(ex) {
return UUID.empty;
}
}
};
UUID["new"] = UUID.create;
w.UUID = w.Guid = UUID;
}(window || this));
The native URL.createObjectURL is generating an UUID. You can take advantage of this.
function uuid() {
const url = URL.createObjectURL(new Blob())
const [id] = url.toString().split('/').reverse()
URL.revokeObjectURL(url)
return id
}
The better way:
function(
a, b // Placeholders
){
for( // Loop :)
b = a = ''; // b - result , a - numeric variable
a++ < 36; //
b += a*51&52 // If "a" is not 9 or 14 or 19 or 24
? // return a random number or 4
(
a^15 // If "a" is not 15,
? // generate a random number from 0 to 15
8^Math.random() *
(a^20 ? 16 : 4) // unless "a" is 20, in which case a random number from 8 to 11,
:
4 // otherwise 4
).toString(16)
:
'-' // In other cases, (if "a" is 9,14,19,24) insert "-"
);
return b
}
Minimized:
function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b}
The following is simple code that uses crypto.getRandomValues(a) on supported browsers (Internet Explorer 11+, iOS 7+, Firefox 21+, Chrome, and Android Chrome).
It avoids using Math.random(), because that can cause collisions (for example 20 collisions for 4000 generated UUIDs in a real situation by Muxa).
function uuid() {
function randomDigit() {
if (crypto && crypto.getRandomValues) {
var rands = new Uint8Array(1);
crypto.getRandomValues(rands);
return (rands[0] % 16).toString(16);
} else {
return ((Math.random() * 16) | 0).toString(16);
}
}
var crypto = window.crypto || window.msCrypto;
return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit);
}
Notes:
Optimised for code readability, not speed, so it is suitable for, say, a few hundred UUIDs per second. It generates about 10000 uuid() per second in Chromium on my laptop using http://jsbin.com/fuwigo/1 to measure performance.
It only uses 8 for "y" because that simplifies code readability (y is allowed to be 8, 9, A, or B).
If you just need a random 128 bit string in no particular format, you can use:
function uuid() {
return crypto.getRandomValues(new Uint32Array(4)).join('-');
}
Which will return something like 2350143528-4164020887-938913176-2513998651.
I couldn't find any answer that uses a single 16-octet TypedArray and a DataView, so I think the following solution for generating a version 4 UUID per the RFC will stand on its own here:
const uuid4 = () => {
const ho = (n, p) => n.toString(16).padStart(p, 0); /// Return the hexadecimal text representation of number `n`, padded with zeroes to be of length `p`
const data = crypto.getRandomValues(new Uint8Array(16)); /// Fill the buffer with random data
data[6] = (data[6] & 0xf) | 0x40; /// Patch the 6th byte to reflect a version 4 UUID
data[8] = (data[8] & 0x3f) | 0x80; /// Patch the 8th byte to reflect a variant 1 UUID (version 4 UUIDs are)
const view = new DataView(data.buffer); /// Create a view backed by a 16-byte buffer
return `${ho(view.getUint32(0), 8)}-${ho(view.getUint16(4), 4)}-${ho(view.getUint16(6), 4)}-${ho(view.getUint16(8), 4)}-${ho(view.getUint32(10), 8)}${ho(view.getUint16(14), 4)}`; /// Compile the canonical textual form from the array data
};
I prefer it because:
it only relies on functions available to the standard ECMAScript platform, where possible -- which is all but one procedure
it only uses a single buffer, minimizing copying of data, which should in theory yield performance advantages
At the time of writing this, getRandomValues is not something implemented for the crypto object in Node.js. However, it has the equivalent randomBytes function which may be used instead.
Just another more readable variant with just two mutations.
function uuid4()
{
function hex (s, b)
{
return s +
(b >>> 4 ).toString (16) + // high nibble
(b & 0b1111).toString (16); // low nibble
}
let r = crypto.getRandomValues (new Uint8Array (16));
r[6] = r[6] >>> 4 | 0b01000000; // Set type 4: 0100
r[8] = r[8] >>> 3 | 0b10000000; // Set variant: 100
return r.slice ( 0, 4).reduce (hex, '' ) +
r.slice ( 4, 6).reduce (hex, '-') +
r.slice ( 6, 8).reduce (hex, '-') +
r.slice ( 8, 10).reduce (hex, '-') +
r.slice (10, 16).reduce (hex, '-');
}

Categories