#[macro_use]
extern crate criterion;
use bytes::{BufMut, BytesMut};
use criterion::Criterion;
use thruster::middleware::query_params::query_params;
use thruster::{
m, decode, middleware_fn, App, BasicContext, MiddlewareNext, MiddlewareResult,
Request,
};
#[middleware_fn]
async fn test_fn_1(
mut context: BasicContext,
_next: MiddlewareNext<BasicContext>,
) -> MiddlewareResult<BasicContext> {
context.body("world");
Ok(context)
}
fn bench_route_match(c: &mut Criterion) {
c.bench_function("Route match", |bench| {
let mut app = App::<Request, BasicContext, ()>::new_basic();
app.get("/test/hello", m!(BasicContext, [test_fn_1]));
let rt = tokio::runtime::Runtime::new().unwrap();
bench.iter(|| {
let mut bytes = BytesMut::with_capacity(47);
bytes.put(&b"GET /test/hello HTTP/1.1\nHost: localhost:8080\n\n"[..]);
let request = decode(&mut bytes).unwrap().unwrap();
let matched =
app.resolve_from_method_and_path(request.method(), request.path().to_owned());
rt.block_on(async {
let _response = app.resolve(request, matched).await.unwrap();
});
});
});
}
fn optimized_bench_route_match(c: &mut Criterion) {
c.bench_function("Optimized route match", |bench| {
let mut app = App::<Request, BasicContext, ()>::new_basic();
app.get("/test/hello", m!(BasicContext, [test_fn_1]));
let rt = tokio::runtime::Runtime::new().unwrap();
bench.iter(|| {
let mut bytes = BytesMut::with_capacity(47);
bytes.put(&b"GET /test/hello HTTP/1.1\nHost: localhost:8080\n\n"[..]);
let request = decode(&mut bytes).unwrap().unwrap();
let matched =
app.resolve_from_method_and_path(request.method(), request.path().to_owned());
rt.block_on(async {
let _response = app.resolve(request, matched).await.unwrap();
});
});
});
}
#[middleware_fn]
async fn test_params_1(
mut context: BasicContext,
_next: MiddlewareNext<BasicContext>,
) -> MiddlewareResult<BasicContext> {
let body = &context
.params
.as_ref()
.unwrap()
.get("hello")
.unwrap()
.clone();
context.body(body);
Ok(context)
}
fn bench_route_match_with_param(c: &mut Criterion) {
c.bench_function("Route match with route params", |bench| {
let mut app = App::<Request, BasicContext, ()>::new_basic();
app.get(
"/test/:hello",
m!(BasicContext, [test_params_1]),
);
let rt = tokio::runtime::Runtime::new().unwrap();
bench.iter(|| {
let mut bytes = BytesMut::with_capacity(48);
bytes.put(&b"GET /test/world HTTP/1.1\nHost: localhost:8080\n\n"[..]);
let request = decode(&mut bytes).unwrap().unwrap();
let matched =
app.resolve_from_method_and_path(request.method(), request.path().to_owned());
rt.block_on(async {
let _response = app.resolve(request, matched).await.unwrap();
});
});
});
}
#[middleware_fn]
async fn test_query_params_1(
mut context: BasicContext,
_next: MiddlewareNext<BasicContext>,
) -> MiddlewareResult<BasicContext> {
let body = &context
.query_params
.as_ref()
.unwrap()
.get("hello")
.unwrap()
.clone();
context.body(body);
Ok(context)
}
fn bench_route_match_with_query_param(c: &mut Criterion) {
c.bench_function("Route match with query params", |bench| {
let mut app = App::<Request, BasicContext, ()>::new_basic();
app.use_middleware("/", m!(BasicContext, [query_params]));
app.get(
"/test",
m!(BasicContext, [test_query_params_1]),
);
let rt = tokio::runtime::Runtime::new().unwrap();
bench.iter(|| {
let mut bytes = BytesMut::with_capacity(54);
bytes.put(&b"GET /test?hello=world HTTP/1.1\nHost: localhost:8080\n\n"[..]);
let request = decode(&mut bytes).unwrap().unwrap();
let matched =
app.resolve_from_method_and_path(request.method(), request.path().to_owned());
rt.block_on(async {
let _response = app.resolve(request, matched).await.unwrap();
});
});
});
}
criterion_group!(
benches,
optimized_bench_route_match,
bench_route_match,
bench_route_match_with_param,
bench_route_match_with_query_param
);
criterion_main!(benches);