diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 000000000..e612126bf --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,28 @@ +name: Benchmark +on: push +jobs: + build: + runs-on: ubuntu-latest + services: + mongodb: + image: mongo:5 + env: + "MONGO_INITDB_ROOT_USERNAME": "root" + "MONGO_INITDB_ROOT_PASSWORD": "password" + ports: + - 27017:27017 + timeout-minutes: 5 + strategy: + matrix: + node-version: [18.x] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - run: make install + - run: make build + - name: Run Benchmark + id: benchmark + run: cd benchmarks/mongodb && node benchmark.js diff --git a/benchmarks/mongodb/benchmark.js b/benchmarks/mongodb/benchmark.js new file mode 100644 index 000000000..656873b15 --- /dev/null +++ b/benchmarks/mongodb/benchmark.js @@ -0,0 +1,56 @@ +const { exec } = require("child_process"); + +async function runScript(scriptPath) { + return new Promise((resolve, reject) => { + exec(`node ${scriptPath}`, (error, stdout, stderr) => { + if (error) { + reject(error); + } + if (stderr) { + reject(stderr); + } + resolve(stdout); + }); + }); +} + +async function main(times = 10, maxDiffInPercentage = 10) { + const results = []; + for (let i = 0; i < times; i++) { + const withGuard = await runScript("withGuard.js"); + const { averageTimeInMS: withGuardTimeInMS } = JSON.parse(withGuard); + const withoutGuard = await runScript("withoutGuard.js"); + const { averageTimeInMS: withoutGuardTimeInMS } = JSON.parse(withoutGuard); + results.push({ + withGuardTimeInMS, + withoutGuardTimeInMS, + differenceInPercentage: Math.abs( + ((withGuardTimeInMS - withoutGuardTimeInMS) / withoutGuardTimeInMS) * + 100 + ), + }); + } + + const averageDifferenceInPercentage = + results + .map((r) => r.differenceInPercentage) + .reduce((acc, diff) => acc + diff, 0) / results.length; + + if (averageDifferenceInPercentage > maxDiffInPercentage) { + console.error( + `The difference between the two benchmarks is too high: ${averageDifferenceInPercentage.toFixed( + 3 + )}%` + ); + console.error(results); + process.exit(1); + } else { + console.log( + `The difference between the two benchmarks is acceptable: ${averageDifferenceInPercentage.toFixed( + 3 + )}%` + ); + } +} + +main(); diff --git a/benchmarks/mongodb/measure.js b/benchmarks/mongodb/measure.js index 344d5bbbf..728525c64 100644 --- a/benchmarks/mongodb/measure.js +++ b/benchmarks/mongodb/measure.js @@ -15,8 +15,5 @@ module.exports = async function measureFunctionPerformance( totalExecutionTime += end - start; } - const averageTime = totalExecutionTime / measuredIterations; - console.log( - `Average execution time over ${measuredIterations} iterations: ${averageTime.toFixed(2)} milliseconds` - ); + return totalExecutionTime / measuredIterations; }; diff --git a/benchmarks/mongodb/withGuard.js b/benchmarks/mongodb/withGuard.js index 46cdb99af..6460c355a 100644 --- a/benchmarks/mongodb/withGuard.js +++ b/benchmarks/mongodb/withGuard.js @@ -7,8 +7,7 @@ const { runWithContext } = require("@aikidosec/guard"); async function main() { const client = await getClient(); - - await measure(async () => { + const averageTimeInMS = await measure(async () => { await runWithContext( { body: { email: "email", password: "password" } }, async () => { @@ -21,6 +20,8 @@ async function main() { }); await client.close(); + + console.log(JSON.stringify({ averageTimeInMS })); } main(); diff --git a/benchmarks/mongodb/withoutGuard.js b/benchmarks/mongodb/withoutGuard.js index 4d4316495..bfaa1b491 100644 --- a/benchmarks/mongodb/withoutGuard.js +++ b/benchmarks/mongodb/withoutGuard.js @@ -4,8 +4,7 @@ const getClient = require("./getClient"); async function main() { const client = await getClient(); - - await measure(async () => { + const averageTimeInMS = await measure(async () => { await getUser(client, { email: "email", password: "password", @@ -13,6 +12,8 @@ async function main() { }); await client.close(); + + console.log(JSON.stringify({ averageTimeInMS })); } main();