Skip to content

Commit

Permalink
Add benchmarks and make sure Node is faster
Browse files Browse the repository at this point in the history
  • Loading branch information
junderw committed Jul 6, 2024
1 parent bfe4c9e commit 4d53643
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 20 deletions.
19 changes: 15 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,28 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm i
- run: npm run unit
benchmarks:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm i
- run: npm run benchmarks
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm i
- run: npm run coverage
Expand All @@ -33,7 +44,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm i
- run: npm run gitdiff:ci
Expand All @@ -43,7 +54,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14
node-version: 20
registry-url: https://registry.npmjs.org/
- run: npm i
- run: npm run lint
72 changes: 72 additions & 0 deletions benchmarks/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Suite } from "bench-node";
import * as nodeTools from "../src/mjs/index.js";
import * as browserTools from "../src/mjs/browser.js";

const DUMMY_BUFFER = Uint8Array.from([
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde,
0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde,
0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
0xbe, 0xef,
]);
const DUMMY_HEX =
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";

// Note: only include benchmarks for functions with differing implementations for Node and Browser
const BENCHMARKS = [
[
`fromHex`,
(library) => () => {
library.fromHex(DUMMY_HEX);
},
],
[
`toHex`,
(library) => () => {
library.toHex(DUMMY_BUFFER);
},
],
];

const LIBRARIES = [
["Node ", nodeTools],
["Browser", browserTools],
];

function setUpSuite(suite, platform, library, funcName, func) {
suite.add(`${platform} ${funcName}`, func(library));
}

async function main() {
const suite = new Suite();
for (const [funcName, func] of BENCHMARKS) {
for (const [name, library] of LIBRARIES) {
setUpSuite(suite, name, library, funcName, func);
}
}
const results = await suite.run();

const nodeSlower = [];

for (let i = 0; i < results.length; i += 2) {
const nodeResult = results[i];
const browserResult = results[i + 1];
if (nodeResult.opsSec < browserResult.opsSec) {
nodeSlower.push(BENCHMARKS[i / 2][0]);
}
}
if (nodeSlower.length > 0) {
throw new Error(
`\n*** Node was slower in the following:\n *** ${nodeSlower.join(
"\n *** "
)}`
);
}
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"types": "src/cjs/index.d.ts",
"type": "module",
"scripts": {
"benchmarks": "node benchmarks/main.js",
"build": "npm run clean && npm run build-ts && npm run convert-cjs && rm -f ./src/cjs/browser.d.ts",
"build-ts": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json",
"clean": "rm -rf ./src/* && rm -rf ./coverage && rm -f ./package-lock.json",
Expand Down Expand Up @@ -50,6 +51,7 @@
"@types/node": "16.11.1",
"@typescript-eslint/eslint-plugin": "5.0.0",
"@typescript-eslint/parser": "5.0.0",
"bench-node": "0.0.1-beta.0",
"eslint": "8.0.1",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-prettier": "4.0.0",
Expand Down
20 changes: 14 additions & 6 deletions src/cjs/index.cjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compare = exports.fromHex = exports.toHex = exports.toUtf8 = void 0;
function toUtf8(bytes) {
return Buffer.from(bytes || []).toString();
}
exports.toUtf8 = toUtf8;
exports.toUtf8 = exports.compare = exports.fromHex = exports.toHex = void 0;
function toHex(bytes) {
return Buffer.from(bytes || []).toString("hex");
}
Expand All @@ -13,7 +9,19 @@ function fromHex(hexString) {
return Uint8Array.from(Buffer.from(hexString || "", "hex"));
}
exports.fromHex = fromHex;
// Same behavior as Buffer.compare()
function compare(v1, v2) {
return Buffer.from(v1).compare(Buffer.from(v2));
const minLength = Math.min(v1.length, v2.length);
for (let i = 0; i < minLength; ++i) {
if (v1[i] !== v2[i]) {
return v1[i] < v2[i] ? -1 : 1;
}
}
return v1.length === v2.length ? 0 : v1.length > v2.length ? 1 : -1;
}
exports.compare = compare;
const DECODER = new TextDecoder();
function toUtf8(bytes) {
return DECODER.decode(bytes);
}
exports.toUtf8 = toUtf8;
2 changes: 1 addition & 1 deletion src/cjs/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export declare function toUtf8(bytes: Uint8Array): string;
export declare function toHex(bytes: Uint8Array): string;
export declare function fromHex(hexString: string): Uint8Array;
export declare type CompareResult = -1 | 0 | 1;
export declare function compare(v1: Uint8Array, v2: Uint8Array): CompareResult;
export declare function toUtf8(bytes: Uint8Array): string;
16 changes: 12 additions & 4 deletions src/mjs/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
export function toUtf8(bytes) {
return Buffer.from(bytes || []).toString();
}
export function toHex(bytes) {
return Buffer.from(bytes || []).toString("hex");
}
export function fromHex(hexString) {
return Uint8Array.from(Buffer.from(hexString || "", "hex"));
}
// Same behavior as Buffer.compare()
export function compare(v1, v2) {
return Buffer.from(v1).compare(Buffer.from(v2));
const minLength = Math.min(v1.length, v2.length);
for (let i = 0; i < minLength; ++i) {
if (v1[i] !== v2[i]) {
return v1[i] < v2[i] ? -1 : 1;
}
}
return v1.length === v2.length ? 0 : v1.length > v2.length ? 1 : -1;
}
const DECODER = new TextDecoder();
export function toUtf8(bytes) {
return DECODER.decode(bytes);
}
20 changes: 15 additions & 5 deletions ts_src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
export function toUtf8(bytes: Uint8Array): string {
return Buffer.from(bytes || []).toString();
}

export function toHex(bytes: Uint8Array): string {
return Buffer.from(bytes || []).toString("hex");
}
Expand All @@ -10,7 +6,21 @@ export function fromHex(hexString: string): Uint8Array {
return Uint8Array.from(Buffer.from(hexString || "", "hex"));
}

// API that is copy-paste from browser

export type CompareResult = -1 | 0 | 1;
// Same behavior as Buffer.compare()
export function compare(v1: Uint8Array, v2: Uint8Array): CompareResult {
return Buffer.from(v1).compare(Buffer.from(v2)) as CompareResult;
const minLength = Math.min(v1.length, v2.length);
for (let i = 0; i < minLength; ++i) {
if (v1[i] !== v2[i]) {
return v1[i] < v2[i] ? -1 : 1;
}
}
return v1.length === v2.length ? 0 : v1.length > v2.length ? 1 : -1;
}

const DECODER = new TextDecoder();
export function toUtf8(bytes: Uint8Array): string {
return DECODER.decode(bytes);
}

0 comments on commit 4d53643

Please sign in to comment.