This repo is intended to measure performance of all popular Node.js web frameworks alongside with the ORM.
List of web framework included in test:
List of ORM included in test:
Running benchmark
npx tsc --project .
node bench.js
Running individual web framework + specific ORM:
npx tsc --project .
# node index.js [web-framework] [orm]
node index.js bare static # open http://localhost:3000
To run the ORM benchmark:
- You need to have a MySQL running in your machine.
- Create a database and import the
CountryCodes.sql
file.
mysql -u root -p -e 'CREATE DATABASE Geo' # create new database
mysql -u root -p Geo < CountryCodes.sql # import from file
app
[name].js
orm
[name].js
The app
folder contains web framework entrypoint. Meanwhile the orm
folder contains ORM definition.
// @ts-check
'use strict'
const c = require('../constanta')
/**
* @param {() => Promise<import("../lib").ICountryCodePair[]>} fetchAll
*/
const createApp = fetchAll => {
// 1. Initialize your application
const app = new MyApp()
// 2. Overview: fetchAll is an async function, your ROOT route of your application
// should be able to handle incoming GET request.
app.get('/', (req, res) => {
fetchAll()
.then(data => {
// If there is no error:
// 2.1. The status code must be 200.
// 2.2. The response must have `Content-Type: application/json; charset=utf-8` header.
// 2.3. The response body must be a valid JSON, which it must be the representation of
// anything that fetchAll function returns.
res.status(200).json(data)
})
.catch(error => {
// If there's an error:
// 2.4. The status code must be 500.
// 2.5. The response must have `Content-Type: application/json; charset=utf-8` header.
// 2.6. The response body must be a valid JSON, which it must be the representation of
// { message: string }
res.status(500).json({ message: error.message )
})
})
// 3. The application must listen on port 3000.
app.listen(3000, () => {
// 3.1. After the application ready to serve connection, send a message to parent process.
process.send && process.send(c['SERVER_EVENT::SERVER_START'])
})
}
// @ts-check
'use strict'
// The ORM should use MySQL as it's datasource
const orm = new MyOrm({
host: 'localhost',
user: 'root',
password: 's3cr3t',
database: 'Geo',
// If you use pool connection, use this configuration:
// - minimum number of connection in your pool: 5
// - maximum number of connection in your pool: 50
pool: {
min: 5,
max: 50
}
})
/**
* @returns {Promise<import("../lib").ICountryCodePair[]>}
*/
const fetchAll = () => new Promise((resolve, reject) => {
// The fetchAll should get all contents in `CountryCodes` table.
orm.fetchAll('CountryCodes', (err, result) {
if (err) {
reject(err)
return
}
resolve(result)
})
})
// Lastly, export the fetchAll function.
exports.fetchAll = fetchAll
Configuration:
- ORM:
static
- AWS tier: t2.large
- Node.js version: v11.13.0
- OS: Ubuntu 18.04.2 LTS
- Kernel: 4.15.0-1032-aws
- Commit ID: 40a1bde
┌──────────────────┬───────────────┬──────────────┬───────────────────┐
│ (index) │ Request (rps) │ Latency (ms) │ Throughput (Mbps) │
├──────────────────┼───────────────┼──────────────┼───────────────────┤
│ fastify:static │ 7,841.280 │ 12.563 │ 210.710 │
│ foxify:static │ 7,698.963 │ 12.790 │ 206.539 │
│ connect:static │ 7,459.340 │ 13.197 │ 200.108 │
│ bare:static │ 7,458.003 │ 13.193 │ 200.058 │
│ koa:static │ 7,138.040 │ 13.787 │ 191.502 │
│ hapi:static │ 5,527.333 │ 17.887 │ 149.684 │
│ express:static │ 5,502.013 │ 17.963 │ 148.947 │
│ restify:static │ 4,582.670 │ 21.447 │ 123.172 │
│ moleculer:static │ 4,099.633 │ 24.023 │ 109.964 │
└──────────────────┴───────────────┴──────────────┴───────────────────┘