#![allow(missing_docs, reason = "benchmark code")]
#![allow(clippy::unwrap_used, reason = "benchmark code")]
#![allow(clippy::missing_panics_doc, reason = "benchmark code")]
#![allow(deprecated, reason = "criterion::black_box is deprecated in favor of std::hint::black_box")]
#![allow(clippy::std_instead_of_core, reason = "benchmark code")]
use std::hint::black_box;
use std::str::FromStr;
use bytes::{Bytes, BytesMut};
use criterion::measurement::WallTime;
use criterion::{BenchmarkGroup, Criterion, criterion_group, criterion_main};
use http::header::{HeaderMap, HeaderName, HeaderValue};
use http::{Method, Request, Response, StatusCode, Version};
use jiff::civil::{Date, DateTime, ISOWeekDate, Time};
use jiff::{SignedDuration, Span, Timestamp};
use thread_aware::ThreadAware;
use thread_aware::affinity::{Affinity, pinned_affinities};
use uuid::Uuid;
fn affinities() -> (Affinity, Affinity) {
let a = pinned_affinities(&[1, 1]);
(a[0], a[1])
}
#[derive(Default)]
struct CounterBody(u64);
impl ThreadAware for CounterBody {
fn relocate(&mut self, _source: Option<Affinity>, _destination: Affinity) {
self.0 = self.0.wrapping_add(1);
}
}
fn build_header_map(n: usize) -> HeaderMap {
let mut m = HeaderMap::with_capacity(n);
for i in 0..n {
let name = HeaderName::from_str(&format!("x-bench-header-{i}")).unwrap();
let value = HeaderValue::from_str(&format!("value-{i}")).unwrap();
m.insert(name, value);
}
m
}
fn build_request<T>(body: T, header_count: usize) -> Request<T> {
let mut req = Request::new(body);
*req.headers_mut() = build_header_map(header_count);
req
}
fn build_response<T>(body: T, header_count: usize) -> Response<T> {
let mut resp = Response::new(body);
*resp.headers_mut() = build_header_map(header_count);
resp
}
fn bench_relocate<T: ThreadAware>(g: &mut BenchmarkGroup<'_, WallTime>, name: &str, mut value: T, src: Affinity, dst: Affinity) {
g.bench_function(name, |b| {
b.iter(|| {
black_box(&mut value).relocate(black_box(Some(src)), black_box(dst));
});
});
}
fn bench_noop_value(c: &mut Criterion) {
let (src, dst) = affinities();
let mut g = c.benchmark_group("noop_value");
bench_relocate(&mut g, "status_code", StatusCode::OK, src, dst);
bench_relocate(&mut g, "method", Method::GET, src, dst);
bench_relocate(&mut g, "version", Version::HTTP_11, src, dst);
bench_relocate(&mut g, "header_name", HeaderName::from_static("x-bench"), src, dst);
bench_relocate(&mut g, "header_value", HeaderValue::from_static("bench-value"), src, dst);
bench_relocate(&mut g, "bytes_empty", Bytes::new(), src, dst);
bench_relocate(&mut g, "bytes_4kb", Bytes::from(vec![0_u8; 4096]), src, dst);
bench_relocate(&mut g, "bytes_mut_4kb", BytesMut::from(&[0_u8; 4096][..]), src, dst);
bench_relocate(&mut g, "uuid", Uuid::nil(), src, dst);
bench_relocate(&mut g, "timestamp", Timestamp::UNIX_EPOCH, src, dst);
bench_relocate(&mut g, "signed_duration", SignedDuration::ZERO, src, dst);
bench_relocate(&mut g, "span", Span::new(), src, dst);
bench_relocate(&mut g, "date", Date::constant(2026, 6, 8), src, dst);
bench_relocate(&mut g, "time", Time::constant(12, 0, 0, 0), src, dst);
bench_relocate(&mut g, "datetime", DateTime::constant(2026, 6, 8, 12, 0, 0, 0), src, dst);
bench_relocate(
&mut g,
"iso_week_date",
ISOWeekDate::new(2026, 23, jiff::civil::Weekday::Monday).unwrap(),
src,
dst,
);
}
fn bench_header_map(c: &mut Criterion) {
let (src, dst) = affinities();
let mut g = c.benchmark_group("header_map");
for (name, count) in [("empty", 0_usize), ("populated_8", 8), ("populated_32", 32)] {
bench_relocate(&mut g, name, build_header_map(count), src, dst);
}
}
fn bench_request(c: &mut Criterion) {
let (src, dst) = affinities();
let mut g = c.benchmark_group("request");
bench_relocate(&mut g, "unit_body_empty_headers", build_request((), 0), src, dst);
bench_relocate(&mut g, "unit_body_populated_headers", build_request((), 32), src, dst);
bench_relocate(&mut g, "bytes_body", build_request(Bytes::from(vec![0_u8; 4096]), 32), src, dst);
bench_relocate(&mut g, "counter_body", build_request(CounterBody::default(), 32), src, dst);
}
fn bench_response(c: &mut Criterion) {
let (src, dst) = affinities();
let mut g = c.benchmark_group("response");
bench_relocate(&mut g, "unit_body_empty_headers", build_response((), 0), src, dst);
bench_relocate(&mut g, "unit_body_populated_headers", build_response((), 32), src, dst);
bench_relocate(&mut g, "bytes_body", build_response(Bytes::from(vec![0_u8; 4096]), 32), src, dst);
bench_relocate(&mut g, "counter_body", build_response(CounterBody::default(), 32), src, dst);
}
criterion_group!(benches, bench_noop_value, bench_header_map, bench_request, bench_response);
criterion_main!(benches);