#[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, ) -> MiddlewareResult { context.body("world"); Ok(context) } fn bench_route_match(c: &mut Criterion) { c.bench_function("Route match", |bench| { let mut app = App::::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::::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, ) -> MiddlewareResult { 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::::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, ) -> MiddlewareResult { 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::::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);