Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions Timestamp48/benchmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

const original = require('./gpt-5.js');
const optimized = require('./optimized.js');

const benchmark = (name, fn, iterations) => {
// Warmup
for (let i = 0; i < 1000; i++) fn();

// Actual benchmark
const start = process.hrtime.bigint();
for (let i = 0; i < iterations; i++) {
fn();
}
const end = process.hrtime.bigint();

const timeMs = Number(end - start) / 1e6;
const opsPerSec = (iterations / timeMs) * 1000;

console.log(`${name}:`);
console.log(` Time: ${timeMs.toFixed(2)}ms`);
console.log(` Ops/sec: ${opsPerSec.toFixed(0)}`);
const avgTime = ((timeMs / iterations) * 1000).toFixed(3);
console.log(` Avg time per op: ${avgTime}μs`);

return { timeMs, opsPerSec };
};

const iterations = 100000;

console.log(`\nBenchmark: ${iterations} UUID generations\n`);
console.log('='.repeat(50));

const originalResult = benchmark(
'Original (gpt-5.js)',
() => original.generateV7Base64Url(),
iterations,
);

console.log('');

const optimizedResult = benchmark(
'Optimized',
() => optimized.generateV7Base64Url(),
iterations,
);

console.log('');

const batchResult = benchmark(
'Batch (10 at once)',
() => optimized.generateBatch(10),
iterations / 10,
);

console.log('\n' + '='.repeat(50));
console.log('\nSummary:');
const perfGain = (
(optimizedResult.opsPerSec / originalResult.opsPerSec - 1) *
100
).toFixed(1);
console.log(` Performance gain: ${perfGain}%`);
const batchEff = (
((batchResult.opsPerSec * 10) / optimizedResult.opsPerSec - 1) *
100
).toFixed(1);
console.log(` Batch efficiency: ${batchEff}% faster per UUID`);
97 changes: 97 additions & 0 deletions Timestamp48/optimized.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use strict';

const crypto = require('crypto');

// Constants for better readability
const VERSION_7 = 0x70;
const VARIANT_RFC4122 = 0x80;
const VARIANT_MASK = 0x3f;
const SEQ_MAX = 0x0fff;

// Pre-allocated buffers for better performance
const sharedBuffer = Buffer.allocUnsafe(16);
const randomPool = Buffer.allocUnsafe(1024);
let poolOffset = 1024;

// State management
const state = {
lastTimestamp: 0n,
sequence: 0,
};

// Get random bytes from pre-allocated pool
const getRandomBytes = (length) => {
if (poolOffset + length > randomPool.length) {
crypto.randomFillSync(randomPool);
poolOffset = 0;
}
const result = randomPool.subarray(poolOffset, poolOffset + length);
poolOffset += length;
return result;
};

// Get current timestamp in milliseconds
const getCurrentTimestamp = () => BigInt(Date.now());

// Pack UUID v7 components into buffer
const packUuidV7 = (timestamp, sequence, randomTail) => {
// Write 48-bit timestamp (big-endian)
sharedBuffer.writeBigUInt64BE(timestamp << 16n, 0);

// Version (7) and sequence high bits
sharedBuffer[6] = VERSION_7 | ((sequence >> 8) & 0x0f);
sharedBuffer[7] = sequence & 0xff;

// RFC 4122 variant and random tail
randomTail.copy(sharedBuffer, 8);
sharedBuffer[8] = (sharedBuffer[8] & VARIANT_MASK) | VARIANT_RFC4122;

return sharedBuffer;
};

/**
* Generates a UUIDv7-like identifier with improved performance
* @returns {string} Base64URL encoded 22-character string
*/
const generateV7Base64Url = () => {
let timestamp = getCurrentTimestamp();

// Handle sequence for monotonicity and counter overflow
if (timestamp <= state.lastTimestamp) {
timestamp = state.lastTimestamp;
state.sequence = (state.sequence + 1) & SEQ_MAX;
if (state.sequence === 0) {
// Sequence overflow, increment timestamp.
// This is a robust way to handle high generation rates
// without busy-waiting for the next millisecond.
timestamp++;
state.lastTimestamp = timestamp;
}
} else {
// New millisecond or time moved backwards: randomize sequence
state.lastTimestamp = timestamp;
// Using random bytes is faster than crypto.randomInt()
state.sequence = getRandomBytes(2).readUInt16BE(0) & SEQ_MAX;
}

// Get random tail from pool
const randomTail = getRandomBytes(8);

// Pack and encode
const packed = packUuidV7(timestamp, state.sequence, randomTail);
return packed.toString('base64url');
};

// Batch generation for better performance
const generateBatch = (count) => {
const results = new Array(count);
for (let i = 0; i < count; i++) {
results[i] = generateV7Base64Url();
}
return results;
};

module.exports = {
generateV7Base64Url,
generateBatch,
};
130 changes: 130 additions & 0 deletions Timestamp48/optimized.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// optimized.mjs - ESM browser-safe version with performance improvements

// Constants
const VERSION_7 = 0x70;
const VARIANT_RFC4122 = 0x80;
const VARIANT_MASK = 0x3f;
const SEQ_MAX = 0x0fff;
const BASE64_CHARS =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';

// Pre-allocated typed arrays for better performance
const sharedBytes = new Uint8Array(16);
const randomPool = new Uint8Array(1024);
let poolOffset = 1024;

// State management
const state = {
lastTimestamp: 0n,
sequence: 0,
};

// Optimized Base64URL encoding
const encodeBase64Url = (bytes) => {
let result = '';
let i = 0;

// Process 3 bytes at a time
while (i < 15) {
const b1 = bytes[i++];
const b2 = bytes[i++];
const b3 = bytes[i++];

result += BASE64_CHARS[b1 >> 2];
result += BASE64_CHARS[((b1 & 3) << 4) | (b2 >> 4)];
result += BASE64_CHARS[((b2 & 15) << 2) | (b3 >> 6)];
result += BASE64_CHARS[b3 & 63];
}

// Handle last byte
const lastByte = bytes[15];
result += BASE64_CHARS[lastByte >> 2];
result += BASE64_CHARS[(lastByte & 3) << 4];

return result;
};

// Get random bytes from pre-allocated pool
const getRandomBytes = (length) => {
if (poolOffset + length > randomPool.length) {
globalThis.crypto.getRandomValues(randomPool);
poolOffset = 0;
}
const result = randomPool.subarray(poolOffset, poolOffset + length);
poolOffset += length;
return result;
};

// Get random 12-bit sequence
const getRandomSequence = () => {
const bytes = getRandomBytes(2);
return ((bytes[0] << 8) | bytes[1]) & SEQ_MAX;
};

// Get current timestamp
const getCurrentTimestamp = () => BigInt(Date.now());

// Pack UUID v7 components
const packUuidV7 = (timestamp, sequence, randomTail) => {
// Write 48-bit timestamp (big-endian)
sharedBytes[0] = Number((timestamp >> 40n) & 0xffn);
sharedBytes[1] = Number((timestamp >> 32n) & 0xffn);
sharedBytes[2] = Number((timestamp >> 24n) & 0xffn);
sharedBytes[3] = Number((timestamp >> 16n) & 0xffn);
sharedBytes[4] = Number((timestamp >> 8n) & 0xffn);
sharedBytes[5] = Number(timestamp & 0xffn);

// Version and sequence
sharedBytes[6] = VERSION_7 | ((sequence >> 8) & 0x0f);
sharedBytes[7] = sequence & 0xff;

// Copy random tail and apply variant
sharedBytes.set(randomTail, 8);
sharedBytes[8] = (sharedBytes[8] & VARIANT_MASK) | VARIANT_RFC4122;

return sharedBytes;
};

/**
* Generates a UUIDv7-like identifier optimized for browser performance
* @returns {string} Base64URL encoded 22-character string
*/
export const generateV7Base64Url = () => {
const now = getCurrentTimestamp();
let timestamp = now > state.lastTimestamp ? now : state.lastTimestamp;

// Handle sequence for monotonicity
if (timestamp === state.lastTimestamp) {
state.sequence = (state.sequence + 1) & SEQ_MAX;
if (state.sequence === 0) {
// Virtual timestamp increment to avoid blocking
timestamp = state.lastTimestamp + 1n;
}
} else {
state.sequence = getRandomSequence();
}

state.lastTimestamp = timestamp;

// Get random tail from pool
const randomTail = getRandomBytes(8);

// Pack and encode
packUuidV7(timestamp, state.sequence, randomTail);
return encodeBase64Url(sharedBytes);
};

/**
* Generate batch of UUIDs for better performance
* @param {number} count - Number of UUIDs to generate
* @returns {Array<string>} Array of Base64URL encoded UUIDs
*/
export const generateBatch = (count) => {
const results = new Array(count);
for (let i = 0; i < count; i++) {
results[i] = generateV7Base64Url();
}
return results;
};

export default generateV7Base64Url;
80 changes: 80 additions & 0 deletions Timestamp48/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

const { test } = require('node:test');
const assert = require('node:assert');
const original = require('./gpt-5.js');
const optimized = require('./optimized.js');

test('UUID format validation', () => {
const uuid1 = original.generateV7Base64Url();
const uuid2 = optimized.generateV7Base64Url();

// Check length (22 chars for Base64URL without padding)
assert.strictEqual(uuid1.length, 22);
assert.strictEqual(uuid2.length, 22);

// Check Base64URL characters
const base64UrlPattern = /^[A-Za-z0-9\-_]+$/;
assert.match(uuid1, base64UrlPattern);
assert.match(uuid2, base64UrlPattern);
});

test('Monotonicity within same millisecond', () => {
const uuids = [];
for (let i = 0; i < 100; i++) {
uuids.push(optimized.generateV7Base64Url());
}

// Check that UUIDs are unique
const uniqueUuids = new Set(uuids);
assert.strictEqual(uniqueUuids.size, uuids.length);
});

test('Batch generation', () => {
const batch = optimized.generateBatch(10);

assert.strictEqual(batch.length, 10);

// Check all are unique
const uniqueBatch = new Set(batch);
assert.strictEqual(uniqueBatch.size, batch.length);

// Check format
batch.forEach((uuid) => {
assert.strictEqual(uuid.length, 22);
assert.match(uuid, /^[A-Za-z0-9\-_]+$/);
});
});

test('Performance comparison', () => {
const iterations = 10000;

// Test original version
const startOriginal = process.hrtime.bigint();
for (let i = 0; i < iterations; i++) {
original.generateV7Base64Url();
}
const endOriginal = process.hrtime.bigint();
// Convert to ms
const timeOriginal = Number(endOriginal - startOriginal) / 1e6;

// Test optimized version
const startOptimized = process.hrtime.bigint();
for (let i = 0; i < iterations; i++) {
optimized.generateV7Base64Url();
}
const endOptimized = process.hrtime.bigint();
const timeOptimized = Number(endOptimized - startOptimized) / 1e6;

console.log(`\nPerformance Results (${iterations} iterations):`);
console.log(`Original: ${timeOriginal.toFixed(2)}ms`);
console.log(`Optimized: ${timeOptimized.toFixed(2)}ms`);
const improvement = ((1 - timeOptimized / timeOriginal) * 100).toFixed(1);
console.log(`Improvement: ${improvement}%`);

// Optimized should be at least as fast
assert.ok(
timeOptimized <= timeOriginal * 1.1,
'Optimized version should not be slower',
);
});