// Adapted from benchmark described in this article https://medium.com/deno-the-complete-reference/node-js-vs-java-how-faster-is-bytecode-compared-to-interpreted-code-for-jwt-sign-verify-910caa55a7f2 // Moves the SHA Key outside of the loop, Brings performance down to ~7 seconds on M3 Macbook Air 24GB RAM import jwt from "jsonwebtoken"; import { readFileSync } from "node:fs"; import { KeyObject } from "node:crypto"; const emails = JSON.parse(readFileSync("./emails.json")); let i = 1, idx = 0; const key = await createHmacKey(process.env.JWT_SECRET ?? "EXAMPLE SECRET KEY"); const keyObject = KeyObject.from(key); // USE THIS INSTEAD OF SECRET STRING const numIterations = 1_010_000; let startTS; while (true) { if (i >= 10_000 && !startTS) { console.log(`Warmup complete`); startTS = performance.now(); } const email = emails[idx]; const currTS = Date.now(); const token = jwt.sign( { sub: email, iat: currTS, exp: currTS + 2 * 60 * 60 * 1000, }, keyObject // THIS WAS ALSO HOT ); const claims = jwt.verify(token, keyObject); // THIS WAS HOT if (claims.sub !== email) { process.exit(1); } if (idx++ >= emails.length) { idx = 0; } if (i++ > numIterations) { break; } } const endTS = performance.now(); const diff = endTS - startTS; console.log(diff); async function createHmacKey(secret) { const enc = new TextEncoder(); const secretKeyData = enc.encode(secret); // Import the secret string as a CryptoKey for HMAC with SHA-256 return await crypto.subtle.importKey( "raw", // Key format secretKeyData, // The raw key data { name: "HMAC", hash: { name: "SHA-256" }, }, false, // Key is not extractable ["sign", "verify"] // Key usages ); }