Skip to content

Instantly share code, notes, and snippets.

@aldy505
Created December 11, 2021 10:50
Show Gist options
  • Save aldy505/097fb864b87be7875d8cd8dff6e4043b to your computer and use it in GitHub Desktop.
Save aldy505/097fb864b87be7875d8cd8dff6e4043b to your computer and use it in GitHub Desktop.
A benchmark between Polka (Nodejs) with Jaguar (Dart)

TLDR: Polka won.

http://localhost:5000 is Jaguar. http://localhost:4000 is Polka.

❯ hyperfine --warmup 2 --min-runs 500 \
> 'curl --request GET \
>   --url http://localhost:5000/ \
>   --header "Accept: application/json" \
>   --header "Content-Type: application/json" \
>   --header "User-Agent: Teknologi Umum Bot" \
>   --data "{\"name\":\"Tikotoni\",\"age\":69,\"rich\":true,\"history\":[\"something\",\"asd\",\"qweqweqwe1\"]}"' \
> 'curl --request GET \
>   --url http://localhost:4000/ \
>   --header "Accept: application/json" \
>   --header "Content-Type: application/json" \
>   --header "User-Agent: Teknologi Umum Bot" \
>   --data "{\"name\":\"Tikotoni\",\"age\":69,\"rich\":true,\"history\":[\"something\",\"asd\",\"qweqweqwe1\"]}"'

Benchmark 1: curl --request GET \
  --url http://localhost:5000/ \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "User-Agent: Teknologi Umum Bot" \
  --data "{\"name\":\"Tikotoni\",\"age\":69,\"rich\":true,\"history\":[\"something\",\"asd\",\"qweqweqwe1\"]}"
  Time (mean ± σ):       9.1 ms ±   1.1 ms    [User: 5.8 ms, System: 2.1 ms]
  Range (min … max):     7.3 ms …  14.5 ms    500 runs

Benchmark 2: curl --request GET \
  --url http://localhost:4000/ \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "User-Agent: Teknologi Umum Bot" \
  --data "{\"name\":\"Tikotoni\",\"age\":69,\"rich\":true,\"history\":[\"something\",\"asd\",\"qweqweqwe1\"]}"
  Time (mean ± σ):       8.2 ms ±   1.1 ms    [User: 5.7 ms, System: 2.0 ms]
  Range (min … max):     6.6 ms …  16.7 ms    500 runs

Summary
  'curl --request GET \
  --url http://localhost:4000/ \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "User-Agent: Teknologi Umum Bot" \
  --data "{\"name\":\"Tikotoni\",\"age\":69,\"rich\":true,\"history\":[\"something\",\"asd\",\"qweqweqwe1\"]}"' ran
    1.11 ± 0.21 times faster than 'curl --request GET \
  --url http://localhost:5000/ \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "User-Agent: Teknologi Umum Bot" \
  --data "{\"name\":\"Tikotoni\",\"age\":69,\"rich\":true,\"history\":[\"something\",\"asd\",\"qweqweqwe1\"]}"'
import 'dart:async';
import 'dart:convert';
import 'package:jaguar/jaguar.dart';
void main() async {
final server = Jaguar(port: 5000);
server.options("/", cors, onException: [handleError]);
server.get("/", handler, before: [cors], onException: [handleError]);
server.post("/", handler, before: [cors], onException: [handleError]);
await server.serve(logRequests: true);
}
FutureOr<dynamic> handler(Context ctx) async {
final body = await parser(ctx);
return Response(
body: json.encode({
"method": ctx.req.method,
"url": ctx.req.uri.toString(),
"headers": ctx.req.headers.toString(),
"body": body,
}),
statusCode: 200,
headers: { "content-type": "application/json" }
);
}
RouteInterceptor cors(Context ctx) {
ctx.response.headers.set("Access-Control-Allow-Origin", "*");
ctx.response.headers.set('Access-Control-Allow-Methods', ['GET', 'POST'].join(', ').toUpperCase());
ctx.response.headers.set('Access-Control-Allow-Headers', 'content-type,accept');
ctx.response.headers.set('Access-Control-Allow-Credentials', 'false');
return null;
}
ExceptionHandler handleError(Context ctx, dynamic exception, StackTrace trace) {
print("exception! " + exception);
return null;
}
Future<dynamic> parser(Context ctx) async {
switch (ctx.req.headers.value("content-type")) {
case "application/json":
return await ctx.bodyAsJsonMap(encoding: utf8);
case "application/x-www-form-urlencoded":
return await ctx.bodyAsUrlEncodedForm(encoding: utf8);
default:
return await ctx.bodyAsText();
}
}
import polka from 'polka';
const main = polka({
onNoMatch: (_, res) => {
res.writeHead(404).end('Not Found');
},
onError: (err, req, res) => {
console.log('Sent an error from the main server');
res.writeHead(err?.code || 500).end(err);
},
});
const cors = (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', ['GET', 'POST'].join(', ').toUpperCase());
res.setHeader('Access-Control-Allow-Headers', 'content-type,accept');
res.setHeader('Access-Control-Allow-Credentials', 'false');
if (req.method.toUpperCase() === 'OPTIONS') {
res.statusCode = 204;
res.setHeader('Content-Length', 0);
res.end();
return;
}
next();
};
const parser = async (req, res, next) => {
try {
let body = '';
for await (const chunk of req) body += chunk;
switch (req.headers['content-type']) {
case 'application/x-www-form-urlencoded':
req.body = querystring.parse(body);
break;
case 'application/json':
req.body = JSON.parse(body);
default:
req.body = body;
}
next();
} catch (error) {
res
.writeHead(400, { 'Content-Type': 'application/json' })
.end(JSON.stringify({ msg: 'Invalid body content with the Content-Type header specification' }));
}
};
main.use(cors);
main.use(parser);
const handler = (req, res) => {
res.writeHead(
200,
{'content-type': 'application/json'}
)
.end(
JSON.stringify(
{
method: req.method,
url: req.originalUrl,
headers: req.headers,
body: req.body
}
)
);
}
main.get('/', handler);
main.post('/', handler);
main.listen(4000, () => console.log('main server running on http://localhost:4000'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment