Skip to content

Commit

Permalink
add benchmark from root
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyjfpender committed Aug 6, 2023
1 parent b2fe3b2 commit ff665ee
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 24 deletions.
8 changes: 3 additions & 5 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
name: Run benchmarks

on:
push:
branches: ["main"]
schedule:
- cron: '0 0 */2 * *'
workflow_dispatch:

permissions:
Expand Down Expand Up @@ -33,9 +33,7 @@ jobs:
pnpm run build
- name: Run benchmarks
run: |
cd packages/credentials
pnpm run benchmark
run: pnpm run benchmark

- name: Commit benchmark results
run: |
Expand Down
40 changes: 40 additions & 0 deletions apps/docs/components/ProofSizeAreaChart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AreaChart, Area, XAxis, YAxis, Tooltip, Legend, CartesianGrid, Label } from 'recharts';
import data from '../public/benchmarks/proof-size.json'; // import JSON data

// Custom Tooltip component
const CustomTooltip = ({ active, payload, label }) => {
if (active) {
return (
<div style={{ backgroundColor: 'rgba(255,255,255,0)', border: 'none', boxShadow: 'none' }}>
<p>{`Date: ${label}`}</p>
<p>{`Size: ${payload[0].value}kB`}</p>
</div>
);
}
return null;
};

function ProofSizeAreaChart() {
return (
<AreaChart width={750} height={400} data={data} margin={{ top: 20, right: 40, left: 100, bottom: 50 }}>
<defs>
<linearGradient id="colorDuration" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#fcba03" stopOpacity={0.8}/>
<stop offset="55%" stopColor="#fcba03" stopOpacity={0}/>
</linearGradient>
</defs>
<XAxis dataKey="name" axisLine={false} height={50}>
<Label value="Date" position="insideBottomLeft" offset={-5} />
</XAxis>
<YAxis axisLine={false} width={80}>
<Label value="Proof Size" angle={-90} position="center" offset={20} />
</YAxis>
<CartesianGrid vertical={false} strokeDasharray="3 3" />
<Tooltip content={<CustomTooltip />} />
<Legend />
<Area type="monotone" dataKey="size" stroke="#fcba03" fillOpacity={1} fill="url(#colorDuration)" />
</AreaChart>
);
}

export default ProofSizeAreaChart;
40 changes: 40 additions & 0 deletions apps/docs/components/ProvingTimeAreaChart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AreaChart, Area, XAxis, YAxis, Tooltip, Legend, CartesianGrid, Label } from 'recharts';
import data from '../public/benchmarks/credential-proving.json'; // import JSON data

// Custom Tooltip component
const CustomTooltip = ({ active, payload, label }) => {
if (active) {
return (
<div style={{ backgroundColor: 'rgba(255,255,255,0)', border: 'none', boxShadow: 'none' }}>
<p>{`Date: ${label}`}</p>
<p>{`Duration: ${payload[0].value}`}</p>
</div>
);
}
return null;
};

function ProvingTimeAreaChart() {
return (
<AreaChart width={750} height={400} data={data} margin={{ top: 20, right: 40, left: 100, bottom: 50 }}>
<defs>
<linearGradient id="colorDuration" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#fcba03" stopOpacity={0.8}/>
<stop offset="55%" stopColor="#fcba03" stopOpacity={0}/>
</linearGradient>
</defs>
<XAxis dataKey="name" axisLine={false} height={50}>
<Label value="Date" position="insideBottomLeft" offset={-5} />
</XAxis>
<YAxis axisLine={false} width={80}>
<Label value="Proving Time" angle={-90} position="center" offset={20} />
</YAxis>
<CartesianGrid vertical={false} strokeDasharray="3 3" />
<Tooltip content={<CustomTooltip />} />
<Legend />
<Area type="monotone" dataKey="duration" stroke="#fcba03" fillOpacity={1} fill="url(#colorDuration)" />
</AreaChart>
);
}

export default ProvingTimeAreaChart;
40 changes: 40 additions & 0 deletions apps/docs/components/VerificationTimeAreaChart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AreaChart, Area, XAxis, YAxis, Tooltip, Legend, CartesianGrid, Label } from 'recharts';
import data from '../public/benchmarks/proof-verifying.json'; // import JSON data

// Custom Tooltip component
const CustomTooltip = ({ active, payload, label }) => {
if (active) {
return (
<div style={{ backgroundColor: 'rgba(255,255,255,0)', border: 'none', boxShadow: 'none' }}>
<p>{`Date: ${label}`}</p>
<p>{`Duration: ${payload[0].value}`}</p>
</div>
);
}
return null;
};

function VerificationTimeAreaChart() {
return (
<AreaChart width={750} height={400} data={data} margin={{ top: 20, right: 40, left: 100, bottom: 50 }}>
<defs>
<linearGradient id="colorDuration" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#fcba03" stopOpacity={0.8}/>
<stop offset="55%" stopColor="#fcba03" stopOpacity={0}/>
</linearGradient>
</defs>
<XAxis dataKey="name" axisLine={false} height={50}>
<Label value="Date" position="insideBottomLeft" offset={-5} />
</XAxis>
<YAxis axisLine={false} width={80}>
<Label value="Verification Time" angle={-90} position="center" offset={20} />
</YAxis>
<CartesianGrid vertical={false} strokeDasharray="3 3" />
<Tooltip content={<CustomTooltip />} />
<Legend />
<Area type="monotone" dataKey="duration" stroke="#fcba03" fillOpacity={1} fill="url(#colorDuration)" />
</AreaChart>
);
}

export default VerificationTimeAreaChart;
17 changes: 14 additions & 3 deletions apps/docs/pages/benchmarks.mdx
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { Steps } from 'nextra-theme-docs'
import SimpleBarChart from '../components/SimpleBarChart'
import ProvingTimeAreaChart from '../components/ProvingTimeAreaChart'
import VerificationTimeAreaChart from '../components/VerificationTimeAreaChart'
import ProofSizeAreaChart from '../components/ProofSizeAreaChart'

# Benchmarks

Add proving & verification benchmarks here
## Proving Time Benchmarks
<div style={{ display: 'flex', justifyContent: 'center', padding: '40px 0' }}>
<ProvingTimeAreaChart />
</div>

## Verification Time Benchmarks
<div style={{ display: 'flex', justifyContent: 'center', padding: '40px 0' }}>
<VerificationTimeAreaChart />
</div>

## Proof Size Benchmarks
<div style={{ display: 'flex', justifyContent: 'center', padding: '40px 0' }}>
<SimpleBarChart />
<ProofSizeAreaChart />
</div>
4 changes: 1 addition & 3 deletions apps/docs/public/benchmarks/credential-proving.json
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
[
{ "name": "Example Date", "duration": 372183}
]
[{"name":"Benchmark 2023-8-5","duration":37},{"name":"Benchmark 2023-8-6","duration":38}]
1 change: 1 addition & 0 deletions apps/docs/public/benchmarks/proof-size.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"name":"Benchmark 2023-8-5","size":37},{"name":"Benchmark 2023-8-6","size":38}]
1 change: 1 addition & 0 deletions apps/docs/public/benchmarks/proof-verifying.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"name":"Benchmark 2023-8-5","duration":37},{"name":"Benchmark 2023-8-6","duration":38}]
21 changes: 21 additions & 0 deletions jest-resolver.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = (request, options) => {
return options.defaultResolver(request, {
...options,
packageFilter: (pkg) => {
// When importing snarkyjs, we specify the Node ESM import as Jest by default imports the web version
if (pkg.name === 'snarkyjs') {
return {
...pkg,
main: pkg.exports.node.import,
};
}
if (pkg.name === 'node-fetch') {
return { ...pkg, main: pkg.main };
}
return {
...pkg,
main: pkg.module || pkg.main,
};
},
});
};
23 changes: 23 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
verbose: true,
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
globals: {
'ts-jest': {
useESM: true,
},
},
testTimeout: 1_000_000,
transform: {
'^.+\\.(t)s$': 'ts-jest',
},
resolver: '<rootDir>/jest-resolver.cjs',
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!(tslib|snarkyjs/node_modules/tslib))',
],
modulePathIgnorePatterns: ['<rootDir>/build/'],
moduleNameMapper: {
'^(\\.{1,2}/.+)\\.js$': '$1',
},
};
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"export": "turbo run export",
"dev": "turbo run dev",
"lint": "turbo run lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"benchmark": "node --experimental-vm-modules --experimental-wasm-threads node_modules/jest/bin/jest.js packages/credentials/test/benchmark.test.ts"
},
"devDependencies": {
"@tsconfig/strictest": "^2.0.1",
Expand All @@ -17,7 +18,9 @@
"tsup": "^6.7.0",
"turbo": "latest",
"typescript": "^5.0.4",
"vitest": "^0.31.4"
"vitest": "^0.31.4",
"@types/jest": "^29.5.3",
"ts-jest": "^29.1.1"
},
"packageManager": "pnpm@8.6.10",
"name": "herald"
Expand Down
35 changes: 25 additions & 10 deletions packages/credentials/test/benchmark.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { PrivateKey, verify } from "snarkyjs";
import { ClaimType, Rule } from "@herald-sdk/data-model";
import { Credential } from "../src";
import { Credential } from "../src/credential";
import fs from 'fs';
import { describe, it } from '@jest/globals';
import benchmarkData from '../../../apps/docs/public/benchmarks/credential-proving.json';

// the relative path to the benchmark data file is as if the test is run from the root of the monorepo
const provingTimeBenchmarkData = JSON.parse(fs.readFileSync('./apps/docs/public/benchmarks/credential-proving.json', 'utf8'));
const verifyingTimeBenchmarkData = JSON.parse(fs.readFileSync('./apps/docs/public/benchmarks/proof-verifying.json', 'utf8'));
const proofSizeBenchmarkData = JSON.parse(fs.readFileSync('./apps/docs/public/benchmarks/proof-size.json', 'utf8'));

describe('Credential Benchmark', () => {
it('benchmark for proving a claim', async () => {
Expand All @@ -13,25 +16,37 @@ describe('Credential Benchmark', () => {
age: 21,
subject: subjectPrvKey.toPublicKey()
};

// todo: change to a W3C credential
const credential = Credential.create(claims, issuerPrvKey);
const property = "age";
const operation = "gte";
const value = 18;
const rule = new Rule(property, operation, value);

// start proving time benchmark
const startTime = Date.now();
const proofResponse = await credential.prove("age", issuerPrvKey.toPublicKey(), rule, subjectPrvKey);
const duration = Date.now() - startTime;
const durationSeconds = duration / 1000;

const date = new Date();
const dateString = `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`;

benchmarkData.push({name: `Benchmark ${dateString}`, duration: duration});
fs.writeFileSync('../../../apps/docs/public/benchmarks/credential-proving.json', JSON.stringify(benchmarkData));


console.log("attestationProof Verification: ", await verify(proofResponse.attestationProof.toJSON(), proofResponse.verificationKey));
provingTimeBenchmarkData.push({name: `${dateString}`, duration: durationSeconds});
fs.writeFileSync('./apps/docs/public/benchmarks/credential-proving.json', JSON.stringify(provingTimeBenchmarkData));
// add proof size to benchmark data
const jsonString = JSON.stringify(proofResponse.attestationProof.toJSON());
const sizeInBytes = new Blob([jsonString]).size;
const sizeInKB = sizeInBytes / 1024;
proofSizeBenchmarkData.push({name: `${dateString}`, size: sizeInKB});
fs.writeFileSync('./apps/docs/public/benchmarks/proof-size.json', JSON.stringify(proofSizeBenchmarkData));
// add verification time to benchmark data
const startTime2 = Date.now();
await verify(proofResponse.attestationProof.toJSON(), proofResponse.verificationKey);
const duration2 = Date.now() - startTime2;
const durationSeconds2 = duration2 / 1000;
verifyingTimeBenchmarkData.push({name: `${dateString}`, duration: durationSeconds2});
fs.writeFileSync('./apps/docs/public/benchmarks/proof-verifying.json', JSON.stringify(verifyingTimeBenchmarkData));

expect(verify(proofResponse.attestationProof.toJSON(), proofResponse.verificationKey)).toBeTruthy();
});
});
3 changes: 2 additions & 1 deletion packages/credentials/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"rootDir": "."
"rootDir": ".",
"baseUrl": "."
},
"include": ["./src/**/*"]
}
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ff665ee

Please sign in to comment.