diff --git a/package-lock.json b/package-lock.json index 943785fc8..b632fd2cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { "name": "@middy/monorepo", - "version": "5.0.3", + "version": "5.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@middy/monorepo", - "version": "5.0.3", + "version": "5.1.0", "hasInstallScript": true, "license": "MIT", "devDependencies": { + "@biomejs/biome": "1.4.0", "@commitlint/cli": "^18.0.0", "@commitlint/config-conventional": "^18.0.0", "@swc/cli": "^0.1.55", @@ -23,6 +24,7 @@ "lint-staged": "^15.0.0", "prettier": "^3.0.0", "sinon": "^17.0.0", + "tinybench": "2.5.1", "ts-standard": "^12.0.0", "tsd": "^0.29.0" }, @@ -193,6 +195,127 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@biomejs/biome": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.4.0.tgz", + "integrity": "sha512-/rDlao6ra38nhxo4IYCqWCzfTJcpMk4YHjSVBI9yN/ifdhnzSwirL25xDVH7G9hZdNhpF9g78FaPJhFa9DX0Cw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.4.0", + "@biomejs/cli-darwin-x64": "1.4.0", + "@biomejs/cli-linux-arm64": "1.4.0", + "@biomejs/cli-linux-x64": "1.4.0", + "@biomejs/cli-win32-arm64": "1.4.0", + "@biomejs/cli-win32-x64": "1.4.0" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", + "integrity": "sha512-nBrtVRwr4IlTtxLOHwBwLv1sWvggf9/DnT5/ALIANJZOpoING6u8jHWipods69wK8kGa8Ld7iwHm3W5BrJJFFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", + "integrity": "sha512-nny0VgOj3ksUGzU5GblgtQEvrAZFgFe1IJBoYOP978OQdDrg7BpS+GX5udfof87Dl4ZlHPRBU951ceHOxF7BTg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.4.0.tgz", + "integrity": "sha512-gyLkT/Yh9xfW1T9yjQs/2txkCeG0e+LRs0adLugMwN0ptcNTRyusBvUoiHnpB+9rS6hWu9ZCedGMNmKQ8v2GSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.4.0.tgz", + "integrity": "sha512-LIxTuU2zSbIHM9XDYjQphJ5UU8h2eS7yR8uIvGYSba7Qt9AKqfbenyVJTsVnoj1CXxxgKNVSc/wVmlOlGz5DBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.4.0.tgz", + "integrity": "sha512-U2jT1/0wZLJIRqnU8qHAfi/A/+yUwlL3sYJgqs+wO0BbR22WGQZlj03u5FdpEoyLXdsLv1pbeIcjNp+V0NYXWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.4.0.tgz", + "integrity": "sha512-gN6DgyyBxIwoCovAUFJHFWVallb0cLosayDRtNyxU3MDv/atZxSXOWQezfVKBIbgmFPxYWJObd+awvbPYXwwww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, "node_modules/@commitlint/cli": { "version": "18.4.3", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.4.3.tgz", @@ -16240,6 +16363,12 @@ "node": ">=4" } }, + "node_modules/tinybench": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", + "dev": true + }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", diff --git a/package.json b/package.json index 9db170a1c..fdd2bee39 100644 --- a/package.json +++ b/package.json @@ -63,13 +63,13 @@ "@swc/core": "^1.2.135", "ava": "^5.0.0", "aws-sdk-client-mock": "^3.0.0", - "benchmark": "^2.1.4", "c8": "^8.0.0", "husky": "^8.0.0", "lerna": "^6.0.0", "lint-staged": "^15.0.0", "prettier": "^3.0.0", "sinon": "^17.0.0", + "tinybench": "^2.5.1", "ts-standard": "^12.0.0", "tsd": "^0.29.0" }, diff --git a/packages/appconfig/__benchmarks__/index.js b/packages/appconfig/__benchmarks__/index.js index 1c94cc095..7ca84c213 100644 --- a/packages/appconfig/__benchmarks__/index.js +++ b/packages/appconfig/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -8,7 +8,7 @@ import { GetSecretValueCommand } from '@aws-sdk/client-appconfig' -const suite = new Benchmark.Suite('@middy/appconfig') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -29,7 +29,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -40,7 +40,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/cloudwatch-metrics/__benchmarks__/index.js b/packages/cloudwatch-metrics/__benchmarks__/index.js index f92fde4af..03b4b1160 100644 --- a/packages/cloudwatch-metrics/__benchmarks__/index.js +++ b/packages/cloudwatch-metrics/__benchmarks__/index.js @@ -1,9 +1,9 @@ /* -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/cloudwatch-metrics') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -17,7 +17,7 @@ const setupHandler = () => { const warmHandler = setupHandler() // TODO fix error -suite +await bench .add('Cold Invocation', async (event = {}) => { const coldHandler = setupHandler() try { @@ -29,7 +29,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) */ + + .run() + +console.table(bench.table()) */ diff --git a/packages/core/__benchmarks__/index.js b/packages/core/__benchmarks__/index.js index 24b9f8561..fe2801e1a 100644 --- a/packages/core/__benchmarks__/index.js +++ b/packages/core/__benchmarks__/index.js @@ -1,35 +1,102 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../index.js' -const suite = new Benchmark.Suite('@middy/core') +const bench = new Bench({ time: 1_000 }) +const middleware = (opts = {}) => { + const middlewareBefore = (request) => {} + const middlewareAfter = (request) => {} + const middlewareOnError = (request) => { + if (request.response !== undefined) return + middlewareAfter(request) + } + return { + before: middlewareBefore, + after: middlewareAfter, + onError: middlewareOnError + } +} +const middlewareAsync = (opts = {}) => { + const middlewareBefore = async (request) => {} + const middlewareAfter = async (request) => {} + const middlewareOnError = async (request) => { + if (request.response !== undefined) return + await middlewareAfter(request) + } + return { + before: middlewareBefore, + after: middlewareAfter, + onError: middlewareOnError + } +} +const baseHandler = () => {} +const baseHandlerAsync = async () => {} const context = { getRemainingTimeInMillis: () => 30000 } -const setupHandler = (timeoutEarlyInMillis = 0) => { - const baseHandler = () => {} - return middy(baseHandler, { timeoutEarlyInMillis }) -} -const warmHandler = setupHandler() -const warmtimeoutHandler = setupHandler(1000) +const warmHandler = middy().handler(baseHandler) +const warmAsyncHandler = middy().handler(baseHandlerAsync) +const middlewares = new Array(25) +middlewares.fill(middleware()) +const warmMiddlewareHandler = middy().use(middlewares).handler(baseHandler) +const middlewaresAsync = new Array(25) +middlewaresAsync.fill(middlewareAsync()) +const warmAsyncMiddlewareHandler = middy() + .use(middlewaresAsync) + .handler(baseHandler) +const warmTimeoutHandler = middy({ timeoutEarlyInMillis: 0 }).handler( + baseHandler +) + +// const warmNextHandler = middyNext().handler(baseHandler) +// const warmNextMiddlewareHandler = middyNext() +// .use([middleware()]) +// .handler(baseHandler) +// const warmNextAsyncMiddlewareHandler = middyNext() +// .use([middlewareAsync()]) +// .handler(baseHandler) +// const warmNextTimeoutHandler = middyNext({ timeoutEarlyInMillis: 0 }).handler( +// baseHandler +// ) -suite +await bench .add('Cold Invocation', async (event = {}) => { - const coldHandler = setupHandler() + const coldHandler = middy().handler(baseHandler) await coldHandler(event, context) }) - .add('Cold Invocation w/ Timeout', async (event = {}) => { - const coldHandler = setupHandler(1000) + .add('Cold Invocation with middleware', async (event = {}) => { + const middlewares = new Array(25) + middlewares.fill(middleware()) + const coldHandler = middy().use(middlewares).handler(baseHandler) await coldHandler(event, context) }) .add('Warm Invocation', async (event = {}) => { await warmHandler(event, context) }) - .add('Warm Invocation with Timeout', async (event = {}) => { - await warmtimeoutHandler(event, context) + // .add('Warm Invocation * next', async (event = {}) => { + // await warmNextHandler(event, context) + // }) + .add('Warm Async Invocation', async (event = {}) => { + await warmAsyncHandler(event, context) }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) + .add('Warm Invocation without Timeout', async (event = {}) => { + await warmTimeoutHandler(event, context) }) - .run({ async: true }) + // .add('Warm Invocation with Timeout * next', async (event = {}) => { + // await warmNextTimeoutHandler(event, context) + // }) + // TODO StreamifyResponse + .add('Warm Invocation with middleware', async (event = {}) => { + await warmMiddlewareHandler(event, context) + }) + // .add('Warm Invocation with middleware * next', async (event = {}) => { + // await warmNextMiddlewareHandler(event, context) + // }) + .add('Warm Invocation with async middleware', async (event = {}) => { + await warmAsyncMiddlewareHandler(event, context) + }) + + .run() + +console.table(bench.table()) diff --git a/packages/core/__tests__/index.js b/packages/core/__tests__/index.js index 408b1ff00..dfd98f1c5 100644 --- a/packages/core/__tests__/index.js +++ b/packages/core/__tests__/index.js @@ -660,125 +660,6 @@ test('"onError" middleware should be able to short circuit response', async (t) t.deepEqual(executed, ['b1', 'e2']) }) -// Plugin -test('Should trigger all plugin hooks', async (t) => { - const plugin = { - beforePrefetch: sinon.spy(), - requestStart: sinon.spy(), - beforeMiddleware: sinon.spy(), - afterMiddleware: sinon.spy(), - beforeHandler: sinon.spy(), - afterHandler: sinon.spy(), - requestEnd: sinon.spy() - } - const beforeMiddleware = sinon.spy() - const lambdaHandler = sinon.spy() - const afterMiddleware = sinon.spy() - - const handler = middy(lambdaHandler, plugin) - .before(beforeMiddleware) - .after(afterMiddleware) - - await handler(event, context) - - t.is(plugin.beforePrefetch.callCount, 1) - t.is(plugin.requestStart.callCount, 1) - t.is(plugin.beforeMiddleware.callCount, 2) - t.is(plugin.afterMiddleware.callCount, 2) - t.is(plugin.beforeHandler.callCount, 1) - t.is(plugin.afterHandler.callCount, 1) - t.is(plugin.requestEnd.callCount, 1) -}) - -test('Should abort handler', async (t) => { - const plugin = { - timeoutEarlyInMillis: 1, - timeoutEarlyResponse: () => true - } - const context = { - getRemainingTimeInMillis: () => 2 - } - - const handler = middy((event, context, { signal }) => { - signal.onabort = function (abort) { - t.true(abort.target.aborted) - } - return Promise.race([]) - }, plugin) - - try { - const response = await handler(event, context) - t.true(response) - } catch (e) {} -}) - -test('Should abort timeout', async (t) => { - const plugin = { - timeoutEarlyInMillis: 50 - } - const context = { - getRemainingTimeInMillis: () => 100 - } - const handler = middy(async (event, context, { signal }) => { - await setTimeout(200) - return true - }, plugin) - - try { - await handler(event, context) - } catch (e) { - t.is(e.name, 'TimeoutError') - t.is(e.message, '[AbortError]: The operation was aborted.') - } -}) - -test('Should not invoke timeoutEarlyResponse on success', async (t) => { - let timeoutCalled = false - const plugin = { - timeoutEarlyInMillis: 50, - timeoutEarlyResponse: () => { - timeoutCalled = true - } - } - const context = { - getRemainingTimeInMillis: () => 100 - } - const handler = middy(async (event, context, { signal }) => { - return true - }, plugin) - - const response = await handler(event, context) - t.true(response) - - await setTimeout(200) - - t.false(timeoutCalled) -}) - -test('Should not invoke timeoutEarlyResponse on error', async (t) => { - let timeoutCalled = false - const plugin = { - timeoutEarlyInMillis: 50, - timeoutEarlyResponse: () => { - timeoutCalled = true - } - } - const context = { - getRemainingTimeInMillis: () => 100 - } - const error = new Error('Oops!') - const handler = middy(async (event, context, { signal }) => { - throw error - }, plugin) - - const response = await handler(event, context).catch((err) => err) - t.is(response, error) - - await setTimeout(100) - - t.false(timeoutCalled) -}) - // streamifyResponse globalThis.awslambda = { streamifyResponse: (cb) => cb, @@ -965,3 +846,122 @@ test('Should return with streamifyResponse:true using body ReadableStream.pipe(. t.is(response, undefined) t.is(chunkResponse, input) }) + +// Plugin +test('Should trigger all plugin hooks', async (t) => { + const plugin = { + beforePrefetch: sinon.spy(), + requestStart: sinon.spy(), + beforeMiddleware: sinon.spy(), + afterMiddleware: sinon.spy(), + beforeHandler: sinon.spy(), + afterHandler: sinon.spy(), + requestEnd: sinon.spy() + } + const beforeMiddleware = sinon.spy() + const lambdaHandler = sinon.spy() + const afterMiddleware = sinon.spy() + + const handler = middy(lambdaHandler, plugin) + .before(beforeMiddleware) + .after(afterMiddleware) + + await handler(event, context) + + t.is(plugin.beforePrefetch.callCount, 1) + t.is(plugin.requestStart.callCount, 1) + t.is(plugin.beforeMiddleware.callCount, 2) + t.is(plugin.afterMiddleware.callCount, 2) + t.is(plugin.beforeHandler.callCount, 1) + t.is(plugin.afterHandler.callCount, 1) + t.is(plugin.requestEnd.callCount, 1) +}) + +test('Should abort handler', async (t) => { + const plugin = { + timeoutEarlyInMillis: 1, + timeoutEarlyResponse: () => true + } + const context = { + getRemainingTimeInMillis: () => 2 + } + + const handler = middy((event, context, { signal }) => { + signal.onabort = function (abort) { + t.true(abort.target.aborted) + } + return Promise.race([]) + }, plugin) + + try { + const response = await handler(event, context) + t.true(response) + } catch (e) {} +}) + +test('Should abort timeout', async (t) => { + const plugin = { + timeoutEarlyInMillis: 50 + } + const context = { + getRemainingTimeInMillis: () => 100 + } + const handler = middy(async (event, context, { signal }) => { + await setTimeout(200) + return true + }, plugin) + + try { + await handler(event, context) + } catch (e) { + t.is(e.name, 'TimeoutError') + t.is(e.message, '[AbortError]: The operation was aborted.') + } +}) + +test('Should not invoke timeoutEarlyResponse on success', async (t) => { + let timeoutCalled = false + const plugin = { + timeoutEarlyInMillis: 50, + timeoutEarlyResponse: () => { + timeoutCalled = true + } + } + const context = { + getRemainingTimeInMillis: () => 100 + } + const handler = middy(async (event, context, { signal }) => { + return true + }, plugin) + + const response = await handler(event, context) + t.true(response) + + await setTimeout(200) + + t.false(timeoutCalled) +}) + +test('Should not invoke timeoutEarlyResponse on error', async (t) => { + let timeoutCalled = false + const plugin = { + timeoutEarlyInMillis: 50, + timeoutEarlyResponse: () => { + timeoutCalled = true + } + } + const context = { + getRemainingTimeInMillis: () => 100 + } + const error = new Error('Oops!') + const handler = middy(async (event, context, { signal }) => { + throw error + }, plugin) + + const response = await handler(event, context).catch((err) => err) + t.is(response, error) + + await setTimeout(100) + + t.false(timeoutCalled) +}) diff --git a/packages/core/index.js b/packages/core/index.js index 5fbb40cb3..8cd484d97 100644 --- a/packages/core/index.js +++ b/packages/core/index.js @@ -95,15 +95,15 @@ const middy = (lambdaHandler = defaultLambdaHandler, plugin = {}) => { for (const middleware of middlewares) { const { before, after, onError } = middleware - if (!before && !after && !onError) { + if (before || after || onError) { + if (before) middy.before(before) + if (after) middy.after(after) + if (onError) middy.onError(onError) + } else { throw new Error( 'Middleware must be an object containing at least one key among "before", "after", "onError"' ) } - - if (before) middy.before(before) - if (after) middy.after(after) - if (onError) middy.onError(onError) } return middy } @@ -138,40 +138,50 @@ const runRequest = async ( plugin ) => { let timeoutAbort + // context.getRemainingTimeInMillis checked for when AWS context missing (tests, containers) const timeoutEarly = - plugin.timeoutEarly && request.context.getRemainingTimeInMillis // disable when AWS context missing (tests, containers) + plugin.timeoutEarly && request.context.getRemainingTimeInMillis + try { await runMiddlewares(request, beforeMiddlewares, plugin) + // Check if before stack hasn't exit early if (typeof request.response === 'undefined') { plugin.beforeHandler?.() + // Note: signal.abort is slow ~6000ns const handlerAbort = new AbortController() - - if (timeoutEarly) timeoutAbort = new AbortController() - request.response = await Promise.race([ + const promises = [ lambdaHandler(request.event, request.context, { signal: handlerAbort.signal - }), - timeoutEarly - ? setTimeout( + }) + ] + + // Can't manually abort and timeout with same AbortSignal + // https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static + if (timeoutEarly) { + timeoutAbort = new AbortController() + promises.push( + setTimeout( request.context.getRemainingTimeInMillis() - - plugin.timeoutEarlyInMillis, + plugin.timeoutEarlyInMillis, undefined, { signal: timeoutAbort.signal } ).then(() => { handlerAbort.abort() return plugin.timeoutEarlyResponse() }) - : Promise.race([]) - ]) - timeoutAbort?.abort() // lambdaHandler may not be a promise + ) + } + request.response = await Promise.race(promises) + timeoutAbort?.abort() // lambdaHandler may not support .then() plugin.afterHandler?.() await runMiddlewares(request, afterMiddlewares, plugin) } } catch (e) { - timeoutAbort?.abort() // timeout should be aborted on errors + // timeout should be aborted when errors happen in handler + timeoutAbort?.abort() // Reset response changes made by after stack before error thrown request.response = undefined diff --git a/packages/do-not-wait-for-empty-event-loop/__benchmarks__/index.js b/packages/do-not-wait-for-empty-event-loop/__benchmarks__/index.js index 2ab95750d..9b32f8231 100644 --- a/packages/do-not-wait-for-empty-event-loop/__benchmarks__/index.js +++ b/packages/do-not-wait-for-empty-event-loop/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/do-not-wait-for-empty-loop') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,13 +14,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Change Context', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/dynamodb/__benchmarks__/index.js b/packages/dynamodb/__benchmarks__/index.js index 2c2327856..7b10e836d 100644 --- a/packages/dynamodb/__benchmarks__/index.js +++ b/packages/dynamodb/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -8,7 +8,7 @@ import { GetSecretValueCommand } from '@aws-sdk/client-dynamodb' -const suite = new Benchmark.Suite('@middy/dynamodb') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -29,7 +29,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -40,7 +40,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/error-logger/__benchmarks__/index.js b/packages/error-logger/__benchmarks__/index.js index 1bce82c37..f76769d25 100644 --- a/packages/error-logger/__benchmarks__/index.js +++ b/packages/error-logger/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/error-logger') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -16,13 +16,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Catch Error', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/event-normalizer/__benchmarks__/index.js b/packages/event-normalizer/__benchmarks__/index.js index c119b7276..a9384a800 100644 --- a/packages/event-normalizer/__benchmarks__/index.js +++ b/packages/event-normalizer/__benchmarks__/index.js @@ -1,9 +1,9 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import createEvent from '@serverless/event-mocks' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/event-normalizer') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -29,7 +29,7 @@ const deepJsonEvent = createEvent.default('aws:sqs') snsEvent.Records[0].Sns.Message = JSON.stringify(sqsEvent) deepJsonEvent.Records[0].body = JSON.stringify(snsEvent) -suite +await bench .add('S3 Event', async (event = { ...s3Event }) => { await warmHandler(event, context) }) @@ -45,7 +45,7 @@ suite .add('Kinesis Event', async (event = { ...kinesisEvent }) => { await warmHandler(event, context) }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-content-encoding/__benchmarks__/index.js b/packages/http-content-encoding/__benchmarks__/index.js index b2d2f5a5a..8d50c762b 100644 --- a/packages/http-content-encoding/__benchmarks__/index.js +++ b/packages/http-content-encoding/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-content-encoding') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -17,7 +17,7 @@ const setupHandler = (options) => { const gzHandler = setupHandler({ preferredEncoding: 'gz' }) const brHandler = setupHandler({ preferredEncoding: 'br' }) -suite +await bench .add('gzip Response', async (event = {}) => { try { await gzHandler(event, context) @@ -28,7 +28,7 @@ suite await brHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-content-negotiation/__benchmarks__/index.js b/packages/http-content-negotiation/__benchmarks__/index.js index ec4604b8d..c08b2eb6b 100644 --- a/packages/http-content-negotiation/__benchmarks__/index.js +++ b/packages/http-content-negotiation/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-content-negotiation') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -21,7 +21,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Parse Headers', async ( @@ -39,7 +39,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-cors/__benchmarks__/index.js b/packages/http-cors/__benchmarks__/index.js index c6d0c71e9..d2b948c45 100644 --- a/packages/http-cors/__benchmarks__/index.js +++ b/packages/http-cors/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-cors') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,13 +14,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Add Headers', async (event = { httpMethod: 'OPTIONS' }) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-error-handler/__benchmarks__/index.js b/packages/http-error-handler/__benchmarks__/index.js index d1defb4d1..3a56c01b1 100644 --- a/packages/http-error-handler/__benchmarks__/index.js +++ b/packages/http-error-handler/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-error-handler') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -16,13 +16,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Handle Error', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-event-normalizer/__benchmarks__/index.js b/packages/http-event-normalizer/__benchmarks__/index.js index 4e7855d91..cf569b58a 100644 --- a/packages/http-event-normalizer/__benchmarks__/index.js +++ b/packages/http-event-normalizer/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-event-normalizer') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,13 +14,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Normalize Event', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-header-normalizer/__benchmarks__/index.js b/packages/http-header-normalizer/__benchmarks__/index.js index 6614d3b99..e46c402ca 100644 --- a/packages/http-header-normalizer/__benchmarks__/index.js +++ b/packages/http-header-normalizer/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-header-normalizer') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -13,7 +13,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Normalize Headers', async ( @@ -33,7 +33,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-json-body-parser/__benchmarks__/index.js b/packages/http-json-body-parser/__benchmarks__/index.js index 7b9c80f9d..edf29c2aa 100644 --- a/packages/http-json-body-parser/__benchmarks__/index.js +++ b/packages/http-json-body-parser/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-json-body-parser') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -13,7 +13,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Parse body', async ( @@ -29,7 +29,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-multipart-body-parser/__benchmarks__/index.js b/packages/http-multipart-body-parser/__benchmarks__/index.js index 130e30da6..a97ef0430 100644 --- a/packages/http-multipart-body-parser/__benchmarks__/index.js +++ b/packages/http-multipart-body-parser/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-multipart-body-parser') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,7 +14,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Parse body', async ( @@ -32,7 +32,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-partial-response/__benchmarks__/index.js b/packages/http-partial-response/__benchmarks__/index.js index e4d4574ee..67375b1dc 100644 --- a/packages/http-partial-response/__benchmarks__/index.js +++ b/packages/http-partial-response/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-partial-response') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -19,7 +19,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Normalize Headers', async ( @@ -34,7 +34,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-response-serializer/__benchmarks__/index.js b/packages/http-response-serializer/__benchmarks__/index.js index d79025c9b..1e02bb8a9 100644 --- a/packages/http-response-serializer/__benchmarks__/index.js +++ b/packages/http-response-serializer/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-response-serializer') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -37,13 +37,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Serialize Response', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-router/__benchmarks__/index.js b/packages/http-router/__benchmarks__/index.js index 03dd302cc..d792bbdcc 100644 --- a/packages/http-router/__benchmarks__/index.js +++ b/packages/http-router/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import router from '../index.js' -const suite = new Benchmark.Suite('@middy/http-router') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -29,7 +29,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'short static', async ( @@ -114,7 +114,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-security-headers/__benchmarks__/index.js b/packages/http-security-headers/__benchmarks__/index.js index a721e4c1f..426ede80e 100644 --- a/packages/http-security-headers/__benchmarks__/index.js +++ b/packages/http-security-headers/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-security-headers') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,13 +14,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('Add Headers', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-urlencode-body-parser/__benchmarks__/index.js b/packages/http-urlencode-body-parser/__benchmarks__/index.js index 9c0b1362f..bb0555f14 100644 --- a/packages/http-urlencode-body-parser/__benchmarks__/index.js +++ b/packages/http-urlencode-body-parser/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-urlencode-body-parser') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,7 +14,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Parse body', async ( @@ -30,7 +30,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/http-urlencode-path-parser/__benchmarks__/index.js b/packages/http-urlencode-path-parser/__benchmarks__/index.js index bac140f19..322957099 100644 --- a/packages/http-urlencode-path-parser/__benchmarks__/index.js +++ b/packages/http-urlencode-path-parser/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/http-urlencode-path-parser') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,7 +14,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Parse body', async ( @@ -29,7 +29,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/input-output-logger/__benchmarks__/index.js b/packages/input-output-logger/__benchmarks__/index.js index 39cae31b2..1cbeddebd 100644 --- a/packages/input-output-logger/__benchmarks__/index.js +++ b/packages/input-output-logger/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/input-output-logger') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000, @@ -22,49 +22,48 @@ const warmHandler = setupHandler({ awsContext: false, omitPaths: [] }) -suite.add( - 'log objects as is', - async ( - event = { foo: [{ foo: 'bar', fuu: { boo: 'baz' } }], hoo: false } - ) => { - try { - await warmHandler(event, context) - } catch (e) {} - } -) const shallowHandler = setupHandler({ awsContext: false, omitPaths: ['event.zooloo', 'event.hoo', 'response.hoo'] }) -suite.add( - 'omit shallow values', - async ( - event = { foo: [{ foo: 'bar', fuu: { boo: 'baz' } }], hoo: false } - ) => { - try { - await shallowHandler(event, context) - } catch (e) {} - } -) const deepHandler = setupHandler({ awsContext: false, omitPaths: ['event.hoo', 'response.foo.[].foo'] }) -suite.add( - 'omit deep values', - async ( - event = { foo: [{ foo: 'bar', fuu: { boo: 'baz' } }], hoo: false } - ) => { - try { - await deepHandler(event, context) - } catch (e) {} - } -) -suite - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) +await bench + .add( + 'log objects as is', + async ( + event = { foo: [{ foo: 'bar', fuu: { boo: 'baz' } }], hoo: false } + ) => { + try { + await warmHandler(event, context) + } catch (e) {} + } + ) + .add( + 'omit shallow values', + async ( + event = { foo: [{ foo: 'bar', fuu: { boo: 'baz' } }], hoo: false } + ) => { + try { + await shallowHandler(event, context) + } catch (e) {} + } + ) + .add( + 'omit deep values', + async ( + event = { foo: [{ foo: 'bar', fuu: { boo: 'baz' } }], hoo: false } + ) => { + try { + await deepHandler(event, context) + } catch (e) {} + } + ) + .run() + +console.table(bench.table()) diff --git a/packages/rds-signer/__benchmarks__/index.js b/packages/rds-signer/__benchmarks__/index.js index 9f501f629..d48c6fff1 100644 --- a/packages/rds-signer/__benchmarks__/index.js +++ b/packages/rds-signer/__benchmarks__/index.js @@ -1,11 +1,11 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' import sinon from 'sinon' import { Signer } from '@aws-sdk/rds-signer' -const suite = new Benchmark.Suite('@middy/rds-signer') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -29,7 +29,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -40,7 +40,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/s3-object-response/__benchmarks__/index.js b/packages/s3-object-response/__benchmarks__/index.js index 822c09800..ac56e0b61 100644 --- a/packages/s3-object-response/__benchmarks__/index.js +++ b/packages/s3-object-response/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -8,7 +8,7 @@ import { S3Client, WriteGetObjectResponseCommand } from '@aws-sdk/client-s3' import { PassThrough } from 'node:stream' import https from 'node:https' -const suite = new Benchmark.Suite('@middy/s3-object-response') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -41,7 +41,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -52,7 +52,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/s3/__benchmarks__/index.js b/packages/s3/__benchmarks__/index.js index d5df374fc..482642966 100644 --- a/packages/s3/__benchmarks__/index.js +++ b/packages/s3/__benchmarks__/index.js @@ -1,11 +1,11 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' import { mockClient } from 'aws-sdk-client-mock' import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-s3' -const suite = new Benchmark.Suite('@middy/s3') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -26,7 +26,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -37,7 +37,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/secrets-manager/__benchmarks__/index.js b/packages/secrets-manager/__benchmarks__/index.js index a07cf39b8..a3953ee36 100644 --- a/packages/secrets-manager/__benchmarks__/index.js +++ b/packages/secrets-manager/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -8,7 +8,7 @@ import { GetSecretValueCommand } from '@aws-sdk/client-secrets-manager' -const suite = new Benchmark.Suite('@middy/secrets-manager') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -29,7 +29,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -40,7 +40,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/service-discovery/__benchmarks__/index.js b/packages/service-discovery/__benchmarks__/index.js index 926706aad..8b87f4a75 100644 --- a/packages/service-discovery/__benchmarks__/index.js +++ b/packages/service-discovery/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -8,7 +8,7 @@ import { DiscoverInstancesCommand } from '@aws-sdk/client-servicediscovery' -const suite = new Benchmark.Suite('@middy/service-discovery') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -42,7 +42,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -53,7 +53,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/sqs-partial-batch-failure/__benchmarks__/index.js b/packages/sqs-partial-batch-failure/__benchmarks__/index.js index 91c3f36a1..d66f346ec 100644 --- a/packages/sqs-partial-batch-failure/__benchmarks__/index.js +++ b/packages/sqs-partial-batch-failure/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/sqs-partial-batch-failure') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -19,13 +19,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('process failures', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/ssm/__benchmarks__/index.js b/packages/ssm/__benchmarks__/index.js index cce1498d4..2468956b1 100644 --- a/packages/ssm/__benchmarks__/index.js +++ b/packages/ssm/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -9,7 +9,7 @@ import { GetParametersByPathCommand } from '@aws-sdk/client-ssm' -const suite = new Benchmark.Suite('@middy/ssm') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -32,7 +32,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -43,7 +43,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/sts/__benchmarks__/index.js b/packages/sts/__benchmarks__/index.js index b3faae379..158ab2291 100644 --- a/packages/sts/__benchmarks__/index.js +++ b/packages/sts/__benchmarks__/index.js @@ -1,11 +1,11 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' import { mockClient } from 'aws-sdk-client-mock' import { STSClient, AssumeRoleCommand } from '@aws-sdk/client-sts' -const suite = new Benchmark.Suite('@middy/rds-signer') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -32,7 +32,7 @@ const setupHandler = (options = {}) => { const coldHandler = setupHandler({ cacheExpiry: 0 }) const warmHandler = setupHandler() -suite +await bench .add('without cache', async (event = {}) => { try { await coldHandler(event, context) @@ -43,7 +43,7 @@ suite await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/util/__benchmarks__/index.js b/packages/util/__benchmarks__/index.js index 1413faef4..59a9e3e6b 100644 --- a/packages/util/__benchmarks__/index.js +++ b/packages/util/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import { getInternal, @@ -7,9 +7,9 @@ import { normalizeHttpResponse } from '../index.js' -const suite = new Benchmark.Suite('@middy/util') +const bench = new Bench({ time: 1_000 }) -suite +await bench .add('getInternal', async (event = {}) => { await getInternal(true, { internal: { @@ -26,7 +26,7 @@ suite .add('normalizeHttpResponse', async (event = {}) => { await normalizeHttpResponse({}) }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/validator/__benchmarks__/index.js b/packages/validator/__benchmarks__/index.js index 160b02fa5..7ffcfb6d4 100644 --- a/packages/validator/__benchmarks__/index.js +++ b/packages/validator/__benchmarks__/index.js @@ -1,9 +1,9 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' import { transpileSchema } from '../transpile.js' -const suite = new Benchmark.Suite('@middy/validator') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -20,13 +20,13 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add('type check input & output', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/warmup/__benchmarks__/index.js b/packages/warmup/__benchmarks__/index.js index 7169a4bb5..4332364cb 100644 --- a/packages/warmup/__benchmarks__/index.js +++ b/packages/warmup/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/warmup') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -14,7 +14,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Change Context', async ( @@ -27,7 +27,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/ws-json-body-parser/__benchmarks__/index.js b/packages/ws-json-body-parser/__benchmarks__/index.js index ceadf13ec..07a9eab48 100644 --- a/packages/ws-json-body-parser/__benchmarks__/index.js +++ b/packages/ws-json-body-parser/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' -const suite = new Benchmark.Suite('@middy/ws-json-body-parser') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -13,7 +13,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'Parse body', async ( @@ -26,7 +26,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/ws-response/__benchmarks__/index.js b/packages/ws-response/__benchmarks__/index.js index f9deac830..03fd4e0d5 100644 --- a/packages/ws-response/__benchmarks__/index.js +++ b/packages/ws-response/__benchmarks__/index.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import middleware from '../index.js' @@ -8,7 +8,7 @@ import { PostToConnectionCommand } from '@aws-sdk/client-apigatewaymanagementapi' -const suite = new Benchmark.Suite('@middy/ws-response') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -34,13 +34,13 @@ const setupHandler = (options = {}) => { const warmHandler = setupHandler() -suite +await bench .add('post message', async (event = {}) => { try { await warmHandler(event, context) } catch (e) {} }) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/packages/ws-router/__benchmarks__/index.js b/packages/ws-router/__benchmarks__/index.js index c74fdbe0a..4ef808cc6 100644 --- a/packages/ws-router/__benchmarks__/index.js +++ b/packages/ws-router/__benchmarks__/index.js @@ -1,8 +1,8 @@ -import Benchmark from 'benchmark' +import { Bench } from 'tinybench' import middy from '../../core/index.js' import router from '../index.js' -const suite = new Benchmark.Suite('@middy/ws-router') +const bench = new Bench({ time: 1_000 }) const context = { getRemainingTimeInMillis: () => 30000 @@ -20,7 +20,7 @@ const setupHandler = () => { const warmHandler = setupHandler() -suite +await bench .add( 'short static', async (event = { requestContext: { routeKey: '$connect' } }) => { @@ -29,7 +29,7 @@ suite } catch (e) {} } ) - .on('cycle', (event) => { - console.log(suite.name, String(event.target)) - }) - .run({ async: true }) + + .run() + +console.table(bench.table()) diff --git a/plugin/hrtime.js b/plugin/hrtime.js new file mode 100644 index 000000000..7728dea50 --- /dev/null +++ b/plugin/hrtime.js @@ -0,0 +1,53 @@ +const defaults = { + logger: console.log, + enabled: true +} + +const timePlugin = (opts = {}) => { + const { logger, enabled } = { ...defaults, ...opts } + if (!enabled) { + return {} + } + + let cold = true + const store = {} + + const start = (id) => { + store[id] = process.hrtime.bigint() + } + const stop = (id) => { + if (!enabled) return + logger( + id, + Number.parseInt((process.hrtime.bigint() - store[id]).toString()) / + 1_000_000, + 'ms' + ) + } + + // Only run during cold start + const beforePrefetch = () => start('prefetch') + const requestStart = () => { + if (cold) { + cold = false + stop('prefetch') + } + start('request') + } + const beforeMiddleware = start + const afterMiddleware = stop + const beforeHandler = () => start('handler') + const afterHandler = () => stop('handler') + const requestEnd = () => stop('request') + + return { + beforePrefetch, + requestStart, + beforeMiddleware, + afterMiddleware, + beforeHandler, + afterHandler, + requestEnd + } +} +export default timePlugin diff --git a/plugin/memory.js b/plugin/memory.js index 999986e88..e929ba768 100644 --- a/plugin/memory.js +++ b/plugin/memory.js @@ -1,11 +1,17 @@ import memwatch from '@airbnb/node-memwatch' const defaults = { - logger: console.log + logger: console.log, + enabled: true } const memoryPlugin = (opts = {}) => { - const { logger } = { ...defaults, ...opts } + const { logger, enabled } = { ...defaults, ...opts } + if (!enabled) { + return {} + } + + let cold = true const store = {} const start = (id) => { @@ -15,16 +21,19 @@ const memoryPlugin = (opts = {}) => { logger(id, store[id].end()) } - const beforePrefetch = () => start('total') + const beforePrefetch = () => start('prefetch') const requestStart = () => { - store.init = store.total - stop('init') + if (cold) { + cold = false + stop('prefetch') + } + start('request') } const beforeMiddleware = start const afterMiddleware = stop const beforeHandler = () => start('handler') const afterHandler = () => stop('handler') - const requestEnd = () => stop('total') + const requestEnd = () => stop('request') return { beforePrefetch, diff --git a/plugin/promise.js b/plugin/promise.js new file mode 100644 index 000000000..eaee500e5 --- /dev/null +++ b/plugin/promise.js @@ -0,0 +1,56 @@ +import { createHook } from 'async_hooks' +const defaults = { + logger: console.log, + enabled: true +} + +let count = 0 +const hook = createHook({ + init (asyncId, type) { + if (type === 'PROMISE') { + count++ + } + } +}) + +const promisePlugin = (opts = {}) => { + const { logger, enabled } = { ...defaults, ...opts } + if (!enabled) { + return {} + } + hook.enable() + + let cold = true + const store = {} + const start = (id) => { + store[id] = count + } + const stop = (id) => { + logger(id, count - store[id]) + } + + const beforePrefetch = () => start('prefetch') + const requestStart = () => { + if (cold) { + cold = false + stop('prefetch') + } + start('request') + } + const beforeMiddleware = start + const afterMiddleware = stop + const beforeHandler = () => start('handler') + const afterHandler = () => stop('handler') + const requestEnd = () => stop('request') + + return { + beforePrefetch, + requestStart, + beforeMiddleware, + afterMiddleware, + beforeHandler, + afterHandler, + requestEnd + } +} +export default promisePlugin diff --git a/plugin/time.js b/plugin/time.js index 70f32a631..0a5a3a9fd 100644 --- a/plugin/time.js +++ b/plugin/time.js @@ -1,3 +1,9 @@ +import { performance, PerformanceObserver } from 'node:perf_hooks' + +const perfObserver = new PerformanceObserver((items) => {}) + +perfObserver.observe({ entryTypes: ['measure'] }) + const defaults = { logger: console.log, enabled: true @@ -5,36 +11,46 @@ const defaults = { const timePlugin = (opts = {}) => { const { logger, enabled } = { ...defaults, ...opts } + if (!enabled) { + return {} + } + + let cold = true const store = {} const start = (id) => { - store[id] = process.hrtime.bigint() + performance.mark(`${id}-start`) } const stop = (id) => { - if (!enabled) return - logger( - id, - Number.parseInt((process.hrtime.bigint() - store[id]).toString()) / - 1_000_000, - 'ms' - ) + performance.mark(`${id}-end`) + const measure = performance.measure(id, `${id}-start`, `${id}-end`) + store[id] = measure.duration + logger(id, measure.duration, 'ms') } // Only run during cold start - const beforePrefetch = () => start('total') + const beforePrefetch = () => { + start('prefetch') + } const requestStart = () => { - if (!store.init) { - store.init = store.total - stop('init') - } else { - start('total') + if (cold) { + cold = false + stop('prefetch') } + start('request') } const beforeMiddleware = start const afterMiddleware = stop const beforeHandler = () => start('handler') const afterHandler = () => stop('handler') - const requestEnd = () => stop('total') + const requestEnd = () => { + stop('request') + // clean up + const ids = Object.keys(store) + const marks = ids.map((id) => [`${id}-start`, `${id}-end`]).flat() + performance.clearMarks(marks) + performance.clearMeasures(ids) + } return { beforePrefetch,