diff --git a/README.md b/README.md index 421553f..0665bce 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,79 @@ All files | 99.79 | 75.67 | 98.63 | 100 | --------------|---------|----------|---------|---------|------------------------------- ``` +## Benchmark +Please benchmark `woodland` on your target hardware to understand the overhead which is expected to be <15% with etags disabled, or <25% with etags enabled. E.g. if `http` can handle 50k req/s, then `woodland` should handle 43k req/s. + +1. Clone repository from [GitHub](https://github.com/avoidwork/woodland). +1. Install dependencies with `npm` or `yarn`. +1. Execute `benchmark` script with `npm` or `yarn`. + +Results with node.js 20.8.0 & an Intel i9-12900HX (mobile) on Windows 11, with etags disabled. + +```console +> node benchmark.js + +http +┌─────────┬──────┬──────┬───────┬───────┬──────────┬──────────┬───────┐ +│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ +├─────────┼──────┼──────┼───────┼───────┼──────────┼──────────┼───────┤ +│ Latency │ 1 ms │ 8 ms │ 42 ms │ 47 ms │ 10.81 ms │ 10.26 ms │ 88 ms │ +└─────────┴──────┴──────┴───────┴───────┴──────────┴──────────┴───────┘ +┌───────────┬─────────┬─────────┬───────┬───────┬─────────┬─────────┬─────────┐ +│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ +├───────────┼─────────┼─────────┼───────┼───────┼─────────┼─────────┼─────────┤ +│ Req/Sec │ 75967 │ 75967 │ 88703 │ 93823 │ 88409.6 │ 4152.76 │ 75952 │ +├───────────┼─────────┼─────────┼───────┼───────┼─────────┼─────────┼─────────┤ +│ Bytes/Sec │ 15.4 MB │ 15.4 MB │ 18 MB │ 19 MB │ 17.9 MB │ 841 kB │ 15.4 MB │ +└───────────┴─────────┴─────────┴───────┴───────┴─────────┴─────────┴─────────┘ + +woodland +┌─────────┬──────┬──────┬───────┬───────┬──────────┬──────────┬────────┐ +│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ +├─────────┼──────┼──────┼───────┼───────┼──────────┼──────────┼────────┤ +│ Latency │ 2 ms │ 9 ms │ 57 ms │ 67 ms │ 12.82 ms │ 13.04 ms │ 119 ms │ +└─────────┴──────┴──────┴───────┴───────┴──────────┴──────────┴────────┘ +┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬─────────┬─────────┐ +│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ +├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤ +│ Req/Sec │ 66687 │ 66687 │ 75263 │ 76095 │ 75041.61 │ 1482.92 │ 66667 │ +├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤ +│ Bytes/Sec │ 14.1 MB │ 14.1 MB │ 15.9 MB │ 16.1 MB │ 15.8 MB │ 312 kB │ 14.1 MB │ +└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴─────────┴─────────┘ + +``` + ## API ### constructor ({...}) Returns a woodland instance. Enable directory browsing & traversal with `autoindex`. Create an automatic `x-response-time` response header with `time` & `digit`. Customize `etag` response header with `seed`. -See configuration options below. +#### Configuration + +```json +{ + "autoindex": false, + "cacheSize": 1000, + "cacheTTL": 300000, + "charset": "utf-8", + "corsExpose": "", + "defaultHeaders": {}, + "digit": 3, + "etags": true, + "indexes": [ + "index.htm", + "index.html" + ], + "logging": { + "enabled": true, + "format": "%h %l %u %t \"%r\" %>s %b", + "level": "info" + }, + "origins": [ + "*" + ], + "time": false +} +``` ### allowed (method, uri, override = false) Calls `routes()` and returns a `Boolean` to indicate if `method` is allowed for `uri`. @@ -71,7 +139,7 @@ Ignores `fn` for calculating the return of `allows()`. Decorates `allow, body, cors, host, ip, params, & parsed` on `req` and `error(status[, body, headers]), header(key, value), json(body[, status, headers]), locals{} & redirect(url[, perm = false])` on `res`. ### etag (...args) -Returns a String to be used as an ETag response header value. +Returns a String to be used as an etag response header value. ### list (method = "get", type = "array") Returns an `Array` or `Object` of routes for the specified method. @@ -106,50 +174,6 @@ Registers middleware for a route. `path` is a regular expression (as a string), All HTTP methods are available on the prototype (partial application of the third argument), e.g. `get([path,] ...fn)` & `options([path,] ...fn)`. -## Benchmark -Please benchmark `woodland` on your target hardware to understand the overhead which is expected to be <15% with etags disabled, or <25% with etags enabled. E.g. if `http` can handle 50k req/s, then `woodland` should handle 43k req/s. - -The performance delta is primarily caused by the native [URL](https://nodejs.org/dist/latest-v18.x/docs/api/url.html) class. - -1. Clone repository from [GitHub](https://github.com/avoidwork/woodland). -1. Install dependencies with `npm` or `yarn`. -1. Execute `benchmark` script with `npm` or `yarn`. - -Results with node.js 20.8.0 & an Intel i9-12900HX (mobile) on Windows 11, with ETags disabled. - -```console -> node benchmark.js - -http -┌─────────┬──────┬──────┬───────┬───────┬──────────┬──────────┬───────┐ -│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ -├─────────┼──────┼──────┼───────┼───────┼──────────┼──────────┼───────┤ -│ Latency │ 1 ms │ 8 ms │ 42 ms │ 47 ms │ 10.81 ms │ 10.26 ms │ 88 ms │ -└─────────┴──────┴──────┴───────┴───────┴──────────┴──────────┴───────┘ -┌───────────┬─────────┬─────────┬───────┬───────┬─────────┬─────────┬─────────┐ -│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ -├───────────┼─────────┼─────────┼───────┼───────┼─────────┼─────────┼─────────┤ -│ Req/Sec │ 75967 │ 75967 │ 88703 │ 93823 │ 88409.6 │ 4152.76 │ 75952 │ -├───────────┼─────────┼─────────┼───────┼───────┼─────────┼─────────┼─────────┤ -│ Bytes/Sec │ 15.4 MB │ 15.4 MB │ 18 MB │ 19 MB │ 17.9 MB │ 841 kB │ 15.4 MB │ -└───────────┴─────────┴─────────┴───────┴───────┴─────────┴─────────┴─────────┘ - -woodland -┌─────────┬──────┬──────┬───────┬───────┬──────────┬──────────┬────────┐ -│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ -├─────────┼──────┼──────┼───────┼───────┼──────────┼──────────┼────────┤ -│ Latency │ 2 ms │ 9 ms │ 57 ms │ 67 ms │ 12.82 ms │ 13.04 ms │ 119 ms │ -└─────────┴──────┴──────┴───────┴───────┴──────────┴──────────┴────────┘ -┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬─────────┬─────────┐ -│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ -├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤ -│ Req/Sec │ 66687 │ 66687 │ 75263 │ 76095 │ 75041.61 │ 1482.92 │ 66667 │ -├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤ -│ Bytes/Sec │ 14.1 MB │ 14.1 MB │ 15.9 MB │ 16.1 MB │ 15.8 MB │ 312 kB │ 14.1 MB │ -└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴─────────┴─────────┘ - -``` - ## Command Line Interface (CLI) When woodland is installed as a global module you can serve the contents of a folder by executing `woodland` in a shell. Optional parameters are `--ip=127.0.0.1` & `--port=8000`. @@ -169,34 +193,6 @@ id=woodland, hostname=localhost, ip=127.0.0.1, port=8000 127.0.0.1 - [7/Oct/2023:15:19:07 -0400] "GET /woodland/sample.js HTTP/1.1" 304 0 ``` -## Configuration - -```json -{ - "autoindex": false, - "cacheSize": 1000, - "cacheTTL": 300000, - "charset": "utf-8", - "corsExpose": "", - "defaultHeaders": {}, - "digit": 3, - "etags": true, - "indexes": [ - "index.htm", - "index.html" - ], - "logging": { - "enabled": true, - "format": "%h %l %u %t \"%r\" %>s %b", - "level": "info" - }, - "origins": [ - "*" - ], - "time": false -} -``` - ## Event Handlers Event Emitter syntax for the following events: diff --git a/dist/woodland.cjs b/dist/woodland.cjs index f240d93..9962df0 100644 --- a/dist/woodland.cjs +++ b/dist/woodland.cjs @@ -3,7 +3,7 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 18.0.7 + * @version 18.0.8 */ 'use strict'; diff --git a/dist/woodland.js b/dist/woodland.js index 9ee49f6..e3aed37 100644 --- a/dist/woodland.js +++ b/dist/woodland.js @@ -3,7 +3,7 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 18.0.7 + * @version 18.0.8 */ import {STATUS_CODES,METHODS}from'node:http';import {join,extname,resolve}from'node:path';import {EventEmitter}from'node:events';import {readFileSync,createReadStream,stat,readdir}from'node:fs';import {etag}from'tiny-etag';import {precise}from'precise';import {lru}from'tiny-lru';import {fileURLToPath,URL}from'node:url';import {coerce}from'tiny-coerce';import mimeDb from'mime-db';const ALL = "*"; const DELIMITER = "|"; diff --git a/package-lock.json b/package-lock.json index affed7d..abe0f50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "woodland", - "version": "18.0.7", + "version": "18.0.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "woodland", - "version": "18.0.7", + "version": "18.0.8", "license": "BSD-3-Clause", "dependencies": { "mime-db": "^1.52.0", diff --git a/package.json b/package.json index a8eef03..5a33a9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woodland", - "version": "18.0.7", + "version": "18.0.8", "description": "Lightweight HTTP framework with automatic headers", "type": "module", "types": "types/woodland.d.ts",