Merge pull request #51 from ChainSafe/dapplion/noble-benchmark

Benchmark noble-bls12-381
This commit is contained in:
Cayman 2020-11-30 16:42:44 -07:00 committed by GitHub
commit 5fee5e367b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 194 additions and 95 deletions

View File

@ -29,4 +29,4 @@ jobs:
run: yarn test:web run: yarn test:web
- name: Benchmark - name: Benchmark
run: yarn benchmark run: yarn benchmark:all

View File

@ -42,7 +42,8 @@
"test:spec": "mocha --colors -r ts-node/register 'test/spec/**/*.test.ts'", "test:spec": "mocha --colors -r ts-node/register 'test/spec/**/*.test.ts'",
"test": "yarn run test:unit && yarn run test:spec", "test": "yarn run test:unit && yarn run test:spec",
"coverage": "codecov -F bls", "coverage": "codecov -F bls",
"benchmark": "ts-node test/benchmark" "benchmark": "ts-node test/benchmark",
"benchmark:all": "cd test/benchmark && yarn install && yarn benchmark"
}, },
"dependencies": { "dependencies": {
"@chainsafe/bls-keygen": "^0.3.0", "@chainsafe/bls-keygen": "^0.3.0",

View File

@ -1,18 +1,19 @@
import {runBenchmark} from "./runner"; import {runBenchmark} from "./runner";
import {runForAllImplementations} from "../switch"; import {runForAllImplementations} from "../switch";
import {IPublicKey, ISignature} from "../../src/interface"; import {IPublicKey, ISignature} from "../../src/interface";
import {randomBytes} from "../../src/helpers"; import {range, randomMessage} from "../util";
runForAllImplementations((bls, implementation) => { const aggCount = 30;
const aggCount = 30;
(async function () {
await runForAllImplementations(async (bls, implementation) => {
// verify // verify
runBenchmark<{pk: IPublicKey; msg: Uint8Array; sig: ISignature}, boolean>({ await runBenchmark<{pk: IPublicKey; msg: Uint8Array; sig: ISignature}, boolean>({
id: `${implementation} verify`, id: `${implementation} verify`,
prepareTest: () => { prepareTest: () => {
const msg = randomMsg(); const msg = randomMessage();
const sk = bls.SecretKey.fromKeygen(); const sk = bls.SecretKey.fromKeygen();
const pk = sk.toPublicKey(); const pk = sk.toPublicKey();
const sig = sk.sign(msg); const sig = sk.sign(msg);
@ -28,11 +29,11 @@ runForAllImplementations((bls, implementation) => {
// Fast aggregate // Fast aggregate
runBenchmark<{pks: IPublicKey[]; msg: Uint8Array; sig: ISignature}, boolean>({ await runBenchmark<{pks: IPublicKey[]; msg: Uint8Array; sig: ISignature}, boolean>({
id: `${implementation} verifyAggregate`, id: `${implementation} verifyAggregate`,
prepareTest: () => { prepareTest: () => {
const msg = randomMsg(); const msg = randomMessage();
const dataArr = range(aggCount).map(() => { const dataArr = range(aggCount).map(() => {
const sk = bls.SecretKey.fromKeygen(); const sk = bls.SecretKey.fromKeygen();
const pk = sk.toPublicKey(); const pk = sk.toPublicKey();
@ -55,7 +56,7 @@ runForAllImplementations((bls, implementation) => {
// Aggregate pubkeys // Aggregate pubkeys
runBenchmark<IPublicKey[], void>({ await runBenchmark<IPublicKey[], void>({
id: `${implementation} aggregate pubkeys (${aggCount})`, id: `${implementation} aggregate pubkeys (${aggCount})`,
prepareTest: () => { prepareTest: () => {
@ -70,11 +71,11 @@ runForAllImplementations((bls, implementation) => {
// Aggregate sigs // Aggregate sigs
runBenchmark<ISignature[], void>({ await runBenchmark<ISignature[], void>({
id: `${implementation} aggregate signatures (${aggCount})`, id: `${implementation} aggregate signatures (${aggCount})`,
prepareTest: () => { prepareTest: () => {
const msg = randomMsg(); const msg = randomMessage();
const sigs = range(aggCount).map(() => { const sigs = range(aggCount).map(() => {
const sk = bls.SecretKey.fromKeygen(); const sk = bls.SecretKey.fromKeygen();
return sk.sign(msg); return sk.sign(msg);
@ -87,14 +88,5 @@ runForAllImplementations((bls, implementation) => {
bls.Signature.aggregate(sigs); bls.Signature.aggregate(sigs);
}, },
}); });
}); });
})();
function range(n: number): number[] {
const nums: number[] = [];
for (let i = 0; i < n; i++) nums.push(i);
return nums;
}
function randomMsg(): Uint8Array {
return randomBytes(32);
}

78
test/benchmark/noble.ts Normal file
View File

@ -0,0 +1,78 @@
import {runBenchmark} from "./runner";
import {range, randomMessage} from "../util";
import {generateRandomSecretKey} from "@chainsafe/bls-keygen";
import * as noble from "noble-bls12-381";
const aggCount = 30;
const nobleRuns = 10;
(async function () {
// verify
await runBenchmark<{pk: Uint8Array; msg: Uint8Array; sig: Uint8Array}, boolean>({
id: `noble verify`,
prepareTest: async () => {
const priv = generateRandomSecretKey();
const msg = randomMessage();
const sig = await noble.sign(msg, priv);
const pk = noble.getPublicKey(priv);
return {
input: {pk, msg, sig},
resultCheck: (valid: boolean) => valid === true,
};
},
testRunner: async ({pk, msg, sig}) => {
return await noble.verify(sig, msg, pk);
},
runs: nobleRuns,
});
// Fast aggregate
await runBenchmark<{pks: Uint8Array[]; msg: Uint8Array; sig: Uint8Array}, boolean>({
id: `noble verifyAggregate`,
prepareTest: async () => {
const msg = randomMessage();
const dataArr = await Promise.all(
range(aggCount).map(async () => {
const sk = generateRandomSecretKey();
const pk = noble.getPublicKey(sk);
const sig = await noble.sign(msg, sk);
return {pk, sig};
})
);
const pks = dataArr.map((data) => data.pk);
const sig = noble.aggregateSignatures(dataArr.map((data) => data.sig));
return {
input: {pks, msg, sig},
resultCheck: (valid: boolean) => valid === true,
};
},
testRunner: async ({pks, msg, sig}) => {
const pk = noble.aggregatePublicKeys(pks);
return await noble.verify(sig, msg, pk);
},
runs: nobleRuns,
});
// Aggregate pubkeys
await runBenchmark<Uint8Array[], void>({
id: `noble aggregate pubkeys (${aggCount})`,
prepareTest: () => {
return {
input: range(aggCount).map(() => noble.getPublicKey(generateRandomSecretKey())),
};
},
testRunner: async (pks) => {
noble.aggregatePublicKeys(pks);
},
runs: nobleRuns,
});
})();

View File

@ -0,0 +1,12 @@
{
"name": "bls-libs-benchmark",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"benchmark": "ts-node index && ts-node noble"
},
"dependencies": {
"noble-bls12-381": "^0.6.1"
}
}

View File

@ -1,21 +1,23 @@
export function runBenchmark<T, R>({ type PromiseOptional<T> = T | Promise<T>;
export async function runBenchmark<T, R>({
prepareTest, prepareTest,
testRunner, testRunner,
runs = 100, runs = 100,
id, id,
}: { }: {
prepareTest: (i: number) => {input: T; resultCheck?: (result: R) => boolean}; prepareTest: (i: number) => PromiseOptional<{input: T; resultCheck?: (result: R) => boolean}>;
testRunner: (input: T) => R; testRunner: (input: T) => PromiseOptional<R>;
runs?: number; runs?: number;
id: string; id: string;
}): void { }): Promise<void> {
const diffsNanoSec: bigint[] = []; const diffsNanoSec: bigint[] = [];
for (let i = 0; i < runs; i++) { for (let i = 0; i < runs; i++) {
const {input, resultCheck} = prepareTest(i); const {input, resultCheck} = await prepareTest(i);
const start = process.hrtime.bigint(); const start = process.hrtime.bigint();
const result = testRunner(input); const result = await testRunner(input);
const end = process.hrtime.bigint(); const end = process.hrtime.bigint();
if (resultCheck && !resultCheck(result)) throw Error("Result fails check test"); if (resultCheck && !resultCheck(result)) throw Error("Result fails check test");

8
test/benchmark/yarn.lock Normal file
View File

@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
noble-bls12-381@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/noble-bls12-381/-/noble-bls12-381-0.6.1.tgz#b44bb5443b4b5c409723f19a8288155f0b3ad126"
integrity sha512-Dt0lq24ez75HqOqNIsxxbzfY7YOuwArtE3H6Clp1XbwnY4Ga1OjFbTaXq5aDBE3+ab1wLK11s0b3yR3+RiWWqw==

View File

@ -7,3 +7,9 @@ export function randomMessage(): Uint8Array {
export function getN<T>(n: number, getter: () => T): T[] { export function getN<T>(n: number, getter: () => T): T[] {
return Array.from({length: n}, () => getter()); return Array.from({length: n}, () => getter());
} }
export function range(n: number): number[] {
const nums: number[] = [];
for (let i = 0; i < n; i++) nums.push(i);
return nums;
}