Skip to content

perf: use crypto.hash when available - #60

Open
pimterry wants to merge 1 commit into
jshttp:masterfrom
pimterry:faster-hash
Open

pimterry wants to merge 1 commit into
jshttp:masterfrom
pimterry:faster-hash

Conversation

@pimterry

@pimterry pimterry commented Sep 3, 2026

Copy link
Copy Markdown

crypto.hash is very significantly faster than the createHash+update+digest dance for small content, and it's now available in all supported Node versions. This PR optimistically uses it when available (20.12.0+) if the body is relatively small (<100KB).

Direct benchmark for the two APIs below, on my machine this makes hashing in etag up to 3.2x faster for small strings, and 2.4x faster for small buffers.

Benchmark:

// Compares the two SHA-1 implementations. No dependencies: node bench.js
var crypto = require('crypto');

function before (entity) {
  return crypto.createHash('sha1').update(entity, 'utf8').digest('base64');
}

function after (entity) {
  return crypto.hash('sha1', entity, 'base64');
}

function time (fn, entity, n) {
  for (var i = 0; i < n; i++) fn(entity); // warm up
  var start = process.hrtime.bigint();
  for (var j = 0; j < n; j++) fn(entity);
  return Number(process.hrtime.bigint() - start) / n;
}

function report (label, entity, n) {
  var was = time(before, entity, n);
  var now = time(after, entity, n);
  console.log(label + ': createHash ' + was.toFixed(0) + 'ns, crypto.hash ' +
    now.toFixed(0) + 'ns, ' + (was / now).toFixed(2) + 'x faster');
}

console.log(process.version);

[10, 100, 1000, 10 * 1024, 100 * 1024, 1_000 * 1024].forEach(function (size) {
  var body = crypto.randomBytes(size);
  var n = 10000;

  report(size + 'B buffer', body, n);
  report(size + 'B string', body.toString('latin1'), n);
})

Results on my machine with latest Node below. Significantly faster up to 10KB, then roughly equal. I tested a bit further (slowly) and it drops off, and docs say >5MB is likely slower. I've put the limit at 100KB here.

➜ node test.js
v26.8.1
10B buffer: createHash 859ns, crypto.hash 353ns, 2.43x faster
10B string: createHash 647ns, crypto.hash 199ns, 3.25x faster
100B buffer: createHash 557ns, crypto.hash 245ns, 2.27x faster
100B string: createHash 687ns, crypto.hash 264ns, 2.60x faster
1000B buffer: createHash 922ns, crypto.hash 597ns, 1.54x faster
1000B string: createHash 1361ns, crypto.hash 953ns, 1.43x faster
10240B buffer: createHash 4926ns, crypto.hash 4465ns, 1.10x faster
10240B string: createHash 7489ns, crypto.hash 7137ns, 1.05x faster
102400B buffer: createHash 42909ns, crypto.hash 42591ns, 1.01x faster
102400B string: createHash 69641ns, crypto.hash 68860ns, 1.01x faster
1024000B buffer: createHash 427863ns, crypto.hash 428869ns, 1.00x faster
1024000B string: createHash 702380ns, crypto.hash 706478ns, 0.99x faster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant