Skip to content

Commit

Permalink
Improve performance (#34)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
bjornstar and sindresorhus authored Jul 29, 2024
1 parent 5d1dad0 commit 1fbfeef
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 46 deletions.
13 changes: 1 addition & 12 deletions browser.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
/* eslint-env browser */

const bufferToHex = buffer => {
const view = new DataView(buffer);

let hexCodes = '';
for (let index = 0; index < view.byteLength; index += 4) {
hexCodes += view.getUint32(index).toString(16).padStart(8, '0');
}

return hexCodes;
};
import {bufferToHex} from './utilities.js';

const create = algorithm => async (buffer, {outputFormat = 'hex'} = {}) => {
if (typeof buffer === 'string') {
Expand Down
21 changes: 4 additions & 17 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Buffer} from 'node:buffer';
import {Worker} from 'node:worker_threads';
import crypto from 'node:crypto';
import {bufferToHex} from './utilities.js';

let create = algorithm => async (buffer, {outputFormat = 'hex'} = {}) => {
const hash = crypto.createHash(algorithm);
Expand Down Expand Up @@ -52,24 +52,11 @@ if (Worker !== undefined) {
});

create = algorithm => async (source, {outputFormat = 'hex'} = {}) => {
let buffer;
if (typeof source === 'string') {
// Saving one copy operation by writing string to buffer right away and then transfering buffer
buffer = new ArrayBuffer(Buffer.byteLength(source, 'utf8'));
Buffer.from(buffer).write(source, 'utf8');
} else {
const finalSource = source instanceof ArrayBuffer ? new Uint8Array(source) : source;

// Creating a copy of buffer at call time, will be transfered later
buffer = finalSource.buffer.slice(0); // eslint-disable-line unicorn/prefer-spread
}
const {buffer} = typeof source === 'string' ? new TextEncoder().encode(source) : (source instanceof ArrayBuffer ? new Uint8Array(source) : source);

const result = await taskWorker({algorithm, buffer}, [buffer]);
if (outputFormat === 'hex') {
return Buffer.from(result).toString('hex');
}
const hash = await taskWorker({algorithm, buffer}, [buffer]);

return result;
return outputFormat === 'hex' ? bufferToHex(hash) : hash;
};
}

Expand Down
7 changes: 6 additions & 1 deletion index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import {expectType} from 'tsd';
import {sha1, sha256, sha384, sha512} from './index.js';
import {
sha1,
sha256,
sha384,
sha512,
} from './index.js';

expectType<Promise<string>>(sha1('🦄'));
expectType<Promise<ArrayBuffer>>(sha1('🦄', {outputFormat: 'buffer'}));
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"index.js",
"index.d.ts",
"browser.js",
"thread.js"
"thread.js",
"utilities.js"
],
"keywords": [
"crypto",
Expand All @@ -43,10 +44,10 @@
"browser"
],
"devDependencies": {
"@sindresorhus/is": "^6.0.1",
"ava": "^5.3.1",
"@sindresorhus/is": "^7.0.0",
"ava": "^6.1.3",
"hash.js": "^1.1.7",
"tsd": "^0.29.0",
"xo": "^0.56.0"
"tsd": "^0.31.1",
"xo": "^0.59.2"
}
}
7 changes: 6 additions & 1 deletion test-browser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/* eslint-env jasmine */
import hashjs from 'hash.js';
import is from '@sindresorhus/is';
import {sha1, sha256, sha384, sha512} from './browser.js';
import {
sha1,
sha256,
sha384,
sha512,
} from './browser.js';

const fixture = 'foo bar baz';

Expand Down
11 changes: 7 additions & 4 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import {Buffer} from 'node:buffer';
import test from 'ava';
import hashjs from 'hash.js';
import is from '@sindresorhus/is';
import {sha1, sha256, sha384, sha512} from './index.js';
import {
sha1,
sha256,
sha384,
sha512,
} from './index.js';

const fixture = 'foo bar baz';

Expand Down Expand Up @@ -33,8 +37,7 @@ test('buffer input', async t => {

test('buffer input - ArrayBuffer', async t => {
const fixture = 'x';
const fixtureBuffer = new ArrayBuffer(Buffer.byteLength(fixture, 'utf8'));
Buffer.from(fixtureBuffer).write(fixture, 'utf8');
const fixtureBuffer = new TextEncoder().encode(fixture).buffer;
t.is(await sha1(fixture), await sha1(fixtureBuffer));
});

Expand Down
10 changes: 4 additions & 6 deletions thread.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import {Buffer} from 'node:buffer';
import crypto from 'node:crypto';
import {parentPort} from 'node:worker_threads';

parentPort.on('message', message => {
const {algorithm, buffer} = message.value;
parentPort.on('message', ({id, value: {algorithm, buffer}}) => {
const hash = crypto.createHash(algorithm);
hash.update(Buffer.from(buffer));
const arrayBuffer = hash.digest().buffer;
hash.update(new DataView(buffer));
const value = hash.digest().buffer;
// Transfering buffer here for consistency, but considering buffer size it might be faster to just leave it for copying, needs perf test
parentPort.postMessage({id: message.id, value: arrayBuffer}, [arrayBuffer]);
parentPort.postMessage({id, value}, [value]);
});
10 changes: 10 additions & 0 deletions utilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const bufferToHex = buffer => {
const view = new DataView(buffer);

let hexCodes = '';
for (let index = 0; index < view.byteLength; index += 4) {
hexCodes += view.getUint32(index).toString(16).padStart(8, '0');
}

return hexCodes;
};

0 comments on commit 1fbfeef

Please sign in to comment.