Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@ You can run the same benchmarks by cloning the repo and then running the followi
npm run benchmark
```

This workload measures the complete HTTP request pipeline with one static `GET /` route. It does not measure how routing performance changes with route count or alternating URLs.

## Router benchmark

The router benchmark registers 1,000 static routes and 100 dynamic routes in both AdonisJS HTTP Server and Fastify. It measures the first and last static and dynamic routes, alternating static and dynamic URLs, and URLs spread over the whole table.

```sh
npm run benchmark:router
```

Each scenario runs for 10 seconds after a shared warmup. The workload can be adjusted with `BENCH_DURATION`, `BENCH_WARMUP_DURATION`, `BENCH_CONNECTIONS`, `BENCH_PIPELINING`, `BENCH_STATIC_ROUTES`, and `BENCH_DYNAMIC_ROUTES`. Set `BENCH_OUTPUT` to save the raw results as JSON and `BENCH_LABEL` to identify the run.

`BENCH_SHAPE` selects how the route table is built. `uniform` (the default) declares every static route before any dynamic one and has no catch-all. `app` mirrors how routes accumulate in a real application: a dynamic route appears early among the static ones, and a top level param route plus a catch-all close the file. Route matching is sensitive to both, so a router change should be measured against each.

```sh
BENCH_SHAPE=app BENCH_STATIC_ROUTES=60 BENCH_DYNAMIC_ROUTES=20 npm run benchmark:router
```

Scenarios built from a single path measure a repeated URL, which per-URL memoisation answers without running the matcher. The `varied-*` scenarios spread requests across the table and are the ones that reflect mixed traffic.

See the [recorded before-and-after results](benchmarks/results/router-comparison.md) for both table shapes.

Since the program correctness and reliability is more important over micro optimizations. We pay penalty on following fronts in comparison to Fastify.

- **The AdonisJS query string parser can parse arrays inside the query string** `(/api?foo[]=bar&foo[]=fuzz&foo[]=buzz
Expand Down
128 changes: 128 additions & 0 deletions benchmarks/results/router-app-after-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
"label": "fixed2",
"timestamp": "2026-08-17T20:04:29.136Z",
"environment": {
"cpu": "Apple M4",
"memory": 34359738368,
"node": "v24.19.0",
"platform": "darwin 24.6.0 arm64"
},
"configuration": {
"staticRoutes": 60,
"dynamicRoutes": 20,
"connections": 100,
"pipelining": 10,
"duration": 10,
"warmupDuration": 3
},
"results": [
{
"framework": "AdonisJS HTTP Server",
"scenario": "static-first",
"requests": 152279.28,
"latency": 6.08
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "static-last",
"requests": 153070.55,
"latency": 6.05
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "dynamic-first",
"requests": 148043.64,
"latency": 6.21
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "dynamic-last",
"requests": 148672,
"latency": 6.19
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "alternating-static",
"requests": 151965.1,
"latency": 6.08
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "alternating-dynamic",
"requests": 140549.82,
"latency": 6.51
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "varied-static",
"requests": 151732.37,
"latency": 6.08
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "varied-dynamic",
"requests": 138234.19,
"latency": 6.89
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "varied-mixed",
"requests": 143458.91,
"latency": 6.31
},
{
"framework": "Fastify",
"scenario": "static-first",
"requests": 115488,
"latency": 8.02
},
{
"framework": "Fastify",
"scenario": "static-last",
"requests": 115109.82,
"latency": 8.01
},
{
"framework": "Fastify",
"scenario": "dynamic-first",
"requests": 115330.91,
"latency": 8.02
},
{
"framework": "Fastify",
"scenario": "dynamic-last",
"requests": 115371.64,
"latency": 8.02
},
{
"framework": "Fastify",
"scenario": "alternating-static",
"requests": 115592.73,
"latency": 7.98
},
{
"framework": "Fastify",
"scenario": "alternating-dynamic",
"requests": 114818.91,
"latency": 8.03
},
{
"framework": "Fastify",
"scenario": "varied-static",
"requests": 114725.82,
"latency": 8.07
},
{
"framework": "Fastify",
"scenario": "varied-dynamic",
"requests": 114638.55,
"latency": 8.09
},
{
"framework": "Fastify",
"scenario": "varied-mixed",
"requests": 113911.28,
"latency": 8.17
}
]
}
128 changes: 128 additions & 0 deletions benchmarks/results/router-app-after-2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
"label": "fixed3",
"timestamp": "2026-08-17T20:08:24.183Z",
"environment": {
"cpu": "Apple M4",
"memory": 34359738368,
"node": "v24.19.0",
"platform": "darwin 24.6.0 arm64"
},
"configuration": {
"staticRoutes": 60,
"dynamicRoutes": 20,
"connections": 100,
"pipelining": 10,
"duration": 10,
"warmupDuration": 3
},
"results": [
{
"framework": "AdonisJS HTTP Server",
"scenario": "static-first",
"requests": 154245.82,
"latency": 5.98
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "static-last",
"requests": 154234.19,
"latency": 6
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "dynamic-first",
"requests": 149661.1,
"latency": 6.19
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "dynamic-last",
"requests": 149312,
"latency": 6.21
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "alternating-static",
"requests": 152942.55,
"latency": 6.06
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "alternating-dynamic",
"requests": 140747.64,
"latency": 6.5
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "varied-static",
"requests": 151732.37,
"latency": 6.09
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "varied-dynamic",
"requests": 139339.64,
"latency": 6.79
},
{
"framework": "AdonisJS HTTP Server",
"scenario": "varied-mixed",
"requests": 144587.64,
"latency": 6.26
},
{
"framework": "Fastify",
"scenario": "static-first",
"requests": 114725.82,
"latency": 8.04
},
{
"framework": "Fastify",
"scenario": "static-last",
"requests": 115598.55,
"latency": 8.01
},
{
"framework": "Fastify",
"scenario": "dynamic-first",
"requests": 114958.55,
"latency": 8.04
},
{
"framework": "Fastify",
"scenario": "dynamic-last",
"requests": 114656,
"latency": 8.07
},
{
"framework": "Fastify",
"scenario": "alternating-static",
"requests": 115866.19,
"latency": 7.97
},
{
"framework": "Fastify",
"scenario": "alternating-dynamic",
"requests": 114365.1,
"latency": 8.09
},
{
"framework": "Fastify",
"scenario": "varied-static",
"requests": 114749.1,
"latency": 8.12
},
{
"framework": "Fastify",
"scenario": "varied-dynamic",
"requests": 115266.91,
"latency": 8.06
},
{
"framework": "Fastify",
"scenario": "varied-mixed",
"requests": 114400,
"latency": 8.17
}
]
}
Loading