Skip to content

Commit

Permalink
New micro-bmark
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillr committed Jan 18, 2025
1 parent 657abce commit 4c4f4e7
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 290 deletions.
39 changes: 16 additions & 23 deletions benchmark/argon.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { run, mark, utils } from 'micro-bmark';
import { argon2id } from '@noble/hashes/argon2';
import * as wasm from 'hash-wasm';
import compare from 'micro-bmark/compare.js';

const ONLY_NOBLE = process.argv[2] === 'noble';
const password = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
const salt = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);

const ITERS = [1, 4, 8];
const MEMORY = [256, 64 * 1024, 256 * 1024, 1 * 1024 * 1024]; // in KB (256kb, 64mb, 256mb, 1gb)

const KDF = {
argon2id: {
'hash-wasm': (iters, mem) =>
Expand All @@ -25,26 +21,23 @@ const KDF = {
},
};

const main = () =>
run(async () => {
for (const i of ITERS) {
for (const m of MEMORY) {
for (let [k, libs] of Object.entries(KDF)) {
const title = `${k} (memory: ${m} KB, iters: ${i})`;
if (!ONLY_NOBLE) console.log(`==== ${title} ====`);
for (const [lib, fn] of Object.entries(libs)) {
if (ONLY_NOBLE && lib !== 'noble') continue;
await mark(!ONLY_NOBLE ? lib : title, 10, () => fn(i, m));
}
if (!ONLY_NOBLE) console.log();
}
}
async function main() {
// basic: node argon.js
// full: MBENCH_DIMS='algorithm,iters,memory,library' node argon.js
await compare(
'Argon',
{
iters: { 1: 1, 4: 4, 8: 8 },
memory: { '256KB': 256, '64MB': 64 * 1024, '256MB': 256 * 1024, '1GB': 1 * 1024 * 1024 },
},
KDF,
{
libDims: ['algorithm', 'library'],
defaults: { library: 'noble', memory: '256KB' },
}
// Log current RAM
utils.logMem();
});
);
}

// ESM is broken.
import url from 'node:url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
console.log(1);
Expand Down
145 changes: 73 additions & 72 deletions benchmark/hashes.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import { mark, utils } from 'micro-bmark';
import compare from 'micro-bmark/compare.js';
// Noble
import { sha256, sha384, sha512 } from '@noble/hashes/sha2';
import { sha256, sha512 } from '@noble/hashes/sha2';
// import { sha224, sha512_256, sha512_384 } from '@noble/hashes/sha2';
import { sha3_256 } from '@noble/hashes/sha3';
import { k12, m14 } from '@noble/hashes/sha3-addons';
import { blake256, blake512 } from '@noble/hashes/blake1';
import { blake2b } from '@noble/hashes/blake2b';
import { blake2s } from '@noble/hashes/blake2s';
import { blake3 } from '@noble/hashes/blake3';
import { ripemd160 } from '@noble/hashes/ripemd160';
import { hmac } from '@noble/hashes/hmac';
import { ripemd160 } from '@noble/hashes/ripemd160';
import { sha3_256 } from '@noble/hashes/sha3';
import { k12, m14 } from '@noble/hashes/sha3-addons';

// Others
import { createHash as crypto_createHash, createHmac as crypto_createHmac } from 'node:crypto';
import createHash from 'create-hash/browser.js';
import createHmac from 'create-hmac/browser.js';
import stable256 from '@stablelib/sha256';
import stableHmac from '@stablelib/hmac';
import { hash as fastsha256 } from 'fast-sha256';
import stable2_384 from '@stablelib/sha384';
import stable2_512 from '@stablelib/sha512';
import stable3 from '@stablelib/sha3';
import stableb2b from '@stablelib/blake2b';
import stableb2s from '@stablelib/blake2s';
import stableHmac from '@stablelib/hmac';
import stable256 from '@stablelib/sha256';
import stable3 from '@stablelib/sha3';
import stable2_512 from '@stablelib/sha512';
import _blakehash from 'blake-hash/js.js';
import createHash from 'create-hash/browser.js';
import createHmac from 'create-hmac/browser.js';
import { hash as fastsha256 } from 'fast-sha256';
import wasm_ from 'hash-wasm';
import jssha3 from 'js-sha3';
import nobleUnrolled from 'unrolled-nbl-hashes-sha3';
import { createHash as crypto_createHash, createHmac as crypto_createHmac } from 'node:crypto';
import { SHA3 as _SHA3 } from 'sha3';
import wasm_ from 'hash-wasm';
import nobleUnrolled from 'unrolled-nbl-hashes-sha3';

const wasm = {};
const wrapBuf = (arrayBuffer) => new Uint8Array(arrayBuffer);
Expand All @@ -42,92 +41,81 @@ const blake_hash = (name) => {
};

const HASHES = {
SHA256: {
sha256: {
noble: (buf) => sha256(buf),
node: (buf) => crypto_createHash('sha256').update(buf).digest(),
'hash-wasm': (buf) => wasm.sha256.init().update(buf).digest(),
'crypto-browserify': (buf) => createHash('sha256').update(buf).digest(),
stablelib: (buf) => stable256.hash(buf),
'fast-sha256': (buf) => fastsha256.hash(buf),
noble: (buf) => sha256(buf),
webcrypto: (buf) => globalThis.crypto.subtle.digest('SHA-256', buf),
},
SHA384: {
node: (buf) => crypto_createHash('sha384').update(buf).digest(),
'crypto-browserify': (buf) => createHash('sha384').update(buf).digest(),
stablelib: (buf) => stable2_384.hash(buf),
noble: (buf) => sha384(buf),
webcrypto: (buf) => globalThis.crypto.subtle.digest('SHA-384', buf),
},
SHA512: {
sha512: {
noble: (buf) => sha512(buf),
node: (buf) => crypto_createHash('sha512').update(buf).digest(),
'hash-wasm': (buf) => wasm.sha512.init().update(buf).digest(),
'crypto-browserify': (buf) => createHash('sha512').update(buf).digest(),
stablelib: (buf) => stable2_512.hash(buf),
noble: (buf) => sha512(buf),
webcrypto: (buf) => globalThis.crypto.subtle.digest('SHA-512', buf),
},
'SHA3-256, keccak256, shake256': {
sha3_256: {
noble: (buf) => sha3_256(buf),
'noble (unrolled)': (buf) => nobleUnrolled.sha3_256(buf),
node: (buf) => crypto_createHash('sha3-256').update(buf).digest(),
'hash-wasm': (buf) => wasm.sha3.init().update(buf).digest(),
stablelib: (buf) => new stable3.SHA3256().update(buf).digest(),
'js-sha3': (buf) => wrapBuf(jssha3.sha3_256.create().update(buf).arrayBuffer()),
sha3: (buf) => new _SHA3(256).update(Buffer.from(buf)).digest(),
'noble (unrolled)': (buf) => nobleUnrolled.sha3_256(buf),
noble: (buf) => sha3_256(buf),
},
Kangaroo12: { noble: (buf) => k12(buf) },
Marsupilami14: { noble: (buf) => m14(buf) },
Blake256: {
'blake-hash': blake_hash('blake256'),
k12: { noble: (buf) => k12(buf) },
m14: { noble: (buf) => m14(buf) },
blake1_256: {
noble: blake256,
'blake-hash': blake_hash('blake256'),
},
Blake512: {
'blake-hash': blake_hash('blake512'),
blake1_512: {
noble: blake512,
'blake-hash': blake_hash('blake512'),
},
BLAKE2b: {
blake2b: {
noble: (buf) => blake2b(buf),
node: (buf) => crypto_createHash('blake2b512').update(buf).digest(),
'hash-wasm': (buf) => wasm.blake2b.init().update(buf).digest(),
stablelib: (buf) => new stableb2b.BLAKE2b().update(buf).digest(),
noble: (buf) => blake2b(buf),
},
BLAKE2s: {
blake2s: {
noble: (buf) => blake2s(buf),
node: (buf) => crypto_createHash('blake2s256').update(buf).digest(),
'hash-wasm': (buf) => wasm.blake2s.init().update(buf).digest(),
stablelib: (buf) => new stableb2s.BLAKE2s().update(buf).digest(),
noble: (buf) => blake2s(buf),
},
BLAKE3: {
'hash-wasm': (buf) => wasm.blake3.init().update(buf).digest(),
blake3: {
noble: (buf) => blake3(buf),
'hash-wasm': (buf) => wasm.blake3.init().update(buf).digest(),
},
RIPEMD160: {
ripemd160: {
noble: (buf) => ripemd160(buf),
node: (buf) => crypto_createHash('ripemd160').update(buf).digest(),
'crypto-browserify': (buf) => createHash('ripemd160').update(Buffer.from(buf)).digest(),
noble: (buf) => ripemd160(buf),
},
'HMAC-SHA256': {
hmac_sha256: {
noble: (buf) => hmac(sha256, buf, buf),
node: (buf) => crypto_createHmac('sha256', buf).update(buf).digest(),
'crypto-browserify': (buf) => createHmac('sha256', buf).update(buf).digest(),
stablelib: (buf) => new stableHmac.HMAC(stable256.SHA256, buf).update(buf).digest(),
noble: (buf) => hmac(sha256, buf, buf),
webcrypto: async (buf) => {
const key = await globalThis.crypto.subtle.importKey('raw', buf, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
const key = await globalThis.crypto.subtle.importKey(
'raw',
buf,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
return await globalThis.crypto.subtle.sign('HMAC', key, buf);
},
},
};

// buffer title, sample count, data
const buffers = {
'32B': [500000, new Uint8Array(32).fill(1)],
// '64B': [200000, new Uint8Array(64).fill(1)],
// '1KB': [50000, new Uint8Array(1024).fill(2)],
// '8KB': [6250, new Uint8Array(1024 * 8).fill(3)],
// // Slow, but 100 doesn't show difference, probably opt doesn't happen or something
// '1MB': [250, new Uint8Array(1024 * 1024).fill(4)],
};

async function main() {
if (!ONLY_NOBLE) {
wasm.sha256 = await wasm_.createSHA256();
Expand All @@ -137,24 +125,37 @@ async function main() {
wasm.blake2s = await wasm_.createBLAKE2s();
wasm.blake3 = await wasm_.createBLAKE3();
}
for (let [k, libs] of Object.entries(HASHES)) {
if (!ONLY_NOBLE) console.log(`==== ${k} ====`);
for (const [size, [samples, buf]] of Object.entries(buffers)) {
for (const [lib, fn] of Object.entries(libs)) {
if (ONLY_NOBLE && lib !== 'noble') continue;
// if (lib !== 'noble') continue;
let title = `${k} ${size}`;
if (!ONLY_NOBLE) title += ` ${lib}`;
await mark(title, samples, () => fn(buf));
}
if (!ONLY_NOBLE) console.log();
// Usage:
// - noble+32B only: node hashes.js
// - noble+diff buffers: MBENCH_DIMS='buffer' node hashes.js
// - others + buffers: MBENCH_DIMS='buffer,algorithm,library' node hashes.js
// - others, but algo first (like old one): MBENCH_DIMS='algorithm,buffer,library' node hashes.js
await compare(
'Hashes',
{
buffer: {
'32B': new Uint8Array(32).fill(1),
'64B': new Uint8Array(64).fill(1),
'1KB': new Uint8Array(1024).fill(2),
'8KB': new Uint8Array(1024 * 8).fill(3),
'1MB': new Uint8Array(1024 * 1024).fill(4),
},
}, //
HASHES,
{
libDims: ['algorithm', 'library'],
defaults: { library: 'noble', buffer: '32B' },
samples: (buf) => {
if (buf.length === 32) return 500_000;
if (buf.length === 64) return 200_000;
if (buf.length === 1024) return 50_000;
if (buf.length === 8 * 1024) return 6_250;
return 250;
},
}
}
// Log current RAM
utils.logMem();
);
}

// ESM is broken.
import url from 'node:url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
main();
Expand Down
45 changes: 45 additions & 0 deletions benchmark/hkdf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import compare from 'micro-bmark/compare.js';
import crypto from 'node:crypto';
// Noble
import { hkdf } from '@noble/hashes/hkdf';
import { sha256 } from '@noble/hashes/sha256';
import { sha512 } from '@noble/hashes/sha512';
// Others
import { HKDF as stableHKDF } from '@stablelib/hkdf';
import stable256 from '@stablelib/sha256';
import stable512 from '@stablelib/sha512';

const [password, salt] = [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])];

const HKDF = {
'HKDF-SHA256': {
node: (len) => crypto.hkdfSync('sha256', password, salt, new Uint8Array(), len),
stable: (len) => new stableHKDF(stable256.SHA256, password, salt, undefined).expand(len),
noble: (len) => hkdf(sha256, salt, password, undefined, len),
},
'HKDF-SHA512': {
node: (len) => crypto.hkdfSync('sha512', password, salt, new Uint8Array(), len),
stable: (len) => new stableHKDF(stable512.SHA512, password, salt, undefined).expand(len),
noble: (len) => hkdf(sha512, salt, password, undefined, len),
},
};

async function main() {
// Usage:
// - basic: node hkdf.js
// - sha256 only: MBENCH_FILTER=SHA256 node hkdf.js
// - full: MBENCH_DIMS='length,algorithm,library' MBENCH_FILTER=SHA256 node hkdf.js
await compare('Hashes', { length: { 32: 32, 64: 64, 256: 256 } }, HKDF, {
libDims: ['algorithm', 'library'],
defaults: { library: 'noble', buffer: '32B' },
samples: (length) => {
if (length <= 64) return 100_000;
return 25_000;
},
});
}

import url from 'node:url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
main();
}
Loading

0 comments on commit 4c4f4e7

Please # to comment.