diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index ce653f440..235e4e980 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -124,3 +124,8 @@ tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" required-features = ["ws", "rustls"] + +[[bench]] +name = "response-body-compression" +harness = false +required-features = ["compress-brotli", "compress-gzip", "compress-zstd"] diff --git a/actix-http/benches/response-body-compression.rs b/actix-http/benches/response-body-compression.rs new file mode 100644 index 000000000..d128bf75b --- /dev/null +++ b/actix-http/benches/response-body-compression.rs @@ -0,0 +1,90 @@ +#![allow(clippy::uninlined_format_args)] + +use std::convert::Infallible; + +use actix_http::{encoding::Encoder, ContentEncoding, Request, Response, StatusCode}; +use actix_service::{fn_service, Service as _}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +static BODY: &[u8] = include_bytes!("../Cargo.toml"); + +fn compression_responses(c: &mut Criterion) { + let mut group = c.benchmark_group("compression responses"); + + group.bench_function("identity", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Identity, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.bench_function("gzip", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Gzip, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.bench_function("br", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Brotli, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.bench_function("zstd", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Zstd, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.finish(); +} + +criterion_group!(benches, compression_responses); +criterion_main!(benches);