Skip to content

Commit

Permalink
perf(toolkit/uuid): use faster algorithm to generate UUID
Browse files Browse the repository at this point in the history
closes #162
  • Loading branch information
ova2 authored and danielwiehl committed Jun 14, 2023
1 parent ac9dd9e commit 1fe7039
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 20 deletions.
2 changes: 1 addition & 1 deletion projects/scion/toolkit/uuid/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
*
* @see https://github.com/ng-packagr/ng-packagr/blob/master/docs/secondary-entrypoints.md
*/
export {UUID} from './uuid.util';
export * as UUID from './uuid.util';
30 changes: 30 additions & 0 deletions projects/scion/toolkit/uuid/src/uuid.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2023 Swiss Federal Railways
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/

import {randomUUID} from './uuid.util';

describe('UUID', () => {

it('should generate an UUID with 36 characters', () => {
const uuid = randomUUID();
expect(uuid).not.toBeNull();
expect(uuid.length === 36).toBeTrue();
});

it('should generate 500_000 unique UUIDs', () => {
// check uniqueness of 500.000 UUIDs
const uuids = new Set();
for (let i = 0; i < 500_000; i++) {
const uuid = randomUUID();
expect(uuids.has(uuid)).toBeFalse();
uuids.add(uuid);
}
});
});
43 changes: 24 additions & 19 deletions projects/scion/toolkit/uuid/src/uuid.util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Swiss Federal Railways
* Copyright (c) 2018-2023 Swiss Federal Railways
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -8,27 +8,32 @@
* SPDX-License-Identifier: EPL-2.0
*/

/**
* Allows generating pseudo-random identifiers.
*/
export class UUID {
const uuidIterator = generateUUID();

private constructor() {
function* generateUUID(): IterableIterator<string> {
const lut = [];
for (let i = 0; i < 256; i++) {
lut[i] = (i < 16 ? '0' : '') + (i).toString(16);
}

/**
* Generates a 'pseudo-random' identifier.
*/
public static randomUUID(): string {
let now = Date.now();
if (typeof window !== 'undefined' && typeof window.performance !== 'undefined' && typeof window.performance.now === 'function') {
now += performance.now(); // use high-precision timer if available
}
while (true) {
const d0 = Math.random() * 0xffffffff | 0;
const d1 = Math.random() * 0xffffffff | 0;
const d2 = Math.random() * 0xffffffff | 0;
const d3 = Math.random() * 0xffffffff | 0;

return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, char => {
const random = (now + Math.random() * 16) % 16 | 0;
now = Math.floor(now / 16);
return (char === 'x' ? random : (random & 0x3 | 0x8)).toString(16);
});
const uuid = 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];

yield uuid;
}
}

/**
* Generates a UUID (universally unique identifier) compliant with the RFC 4122 version 4.
*/
export function randomUUID(): string {
return uuidIterator.next().value;
}

0 comments on commit 1fe7039

Please sign in to comment.