use dever_runtime::wire::serde::{self, Deserialize, Serialize}; use dever_runtime::{ api::{Request, Response}, task::{Limits, Runtime, Scope}, }; use std::future::Future; struct Input<'scope> { request: Request, peer: std::net::SocketAddr, scope: &'scope Scope<'scope>, } fn fault(_: impl std::fmt::Display) -> Fault { &FaultInfo { message: "HTTP input failure", source: "api-reference", line: 1, column: 1, } } // 此样例不挂起;直接轮询实际生成入口,计时不含网络与调度器启动。 fn generated(values: &[Input<'_>]) -> Result, Fault> { let Some(value) = values.first() else { return Ok(Vec::new()); }; let future = async { if value.request.uri().path() == "/bench/wire/count" { GENERATED_LIST(&value.request, value.peer, value.scope).await } else { GENERATED_HTTP(&value.request, value.peer, value.scope).await } }; let mut future = std::pin::pin!(future); let mut context = std::task::Context::from_waker(std::task::Waker::noop()); let std::task::Poll::Ready(response) = future.as_mut().poll(&mut context) else { panic!("pure HTTP fixture unexpectedly suspended"); }; if response.status() != 200 { return Err(fault(response.status())); } Ok(response.into_body().into()) } #[derive(Deserialize, Serialize)] #[serde(crate = "dever_runtime::wire::serde", deny_unknown_fields)] struct Payload { text: String, value: i64, } #[derive(Deserialize)] #[serde(crate = "dever_runtime::wire::serde", deny_unknown_fields)] struct Arguments { payload: Object, } #[derive(Deserialize)] #[serde(crate = "dever_runtime::wire::serde", deny_unknown_fields)] struct ListArguments { values: Integers, } struct Integers(Vec); impl<'input> Deserialize<'input> for Integers { fn deserialize>( decoder: Decoder, ) -> Result { struct Visitor; impl<'input> serde::de::Visitor<'input> for Visitor { type Value = Integers; fn expecting(&self, output: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { output.write_str("an integer array") } fn visit_seq>( self, mut access: Access, ) -> Result { let mut values = Vec::new(); while let Some(value) = access.next_element()? { // 根对象和数组各占一个值;检查与 Serde 解码在同一次遍历中完成。 if values.len() == 65536 - 2 { return Err(serde::de::Error::custom("value limit")); } values.push(value); } Ok(Integers(values)) } } decoder.deserialize_seq(Visitor) } } struct Object(Value); impl<'input, Value: Deserialize<'input>> Deserialize<'input> for Object { fn deserialize>( decoder: Decoder, ) -> Result { struct Visitor(std::marker::PhantomData); impl<'input, Value: Deserialize<'input>> serde::de::Visitor<'input> for Visitor { type Value = Value; fn expecting(&self, output: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { output.write_str("an object") } fn visit_map>( self, access: Access, ) -> Result { Value::deserialize(serde::de::value::MapAccessDeserializer::new(access)) } } decoder .deserialize_map(Visitor(std::marker::PhantomData)) .map(Self) } } // 独立使用 Serde;固定记录保证结构预算,字节预算在唯一输入/输出边界处理。 fn reference(values: &[Input<'_>]) -> Result, Fault> { let Some(value) = values.first() else { return Ok(Vec::new()); }; let request = &value.request; let mut headers = request.headers().get_all("content-type").iter(); let content = headers.next().ok_or_else(|| fault("content type"))?; let content = std::str::from_utf8(content.as_bytes()).map_err(fault)?; if !content .split(';') .next() .unwrap() .trim() .eq_ignore_ascii_case("application/json") || headers.next().is_some() { return Err(fault("content type")); } if request.body().len() > 16 * 1024 * 1024 { return Err(fault("input size")); } let text = std::str::from_utf8(request.body()).map_err(fault)?; #[derive(Serialize)] #[serde(crate = "dever_runtime::wire::serde")] struct Envelope { code: u16, message: &'static str, data: Value, } struct Output(Vec); impl std::io::Write for Output { fn write(&mut self, bytes: &[u8]) -> std::io::Result { if bytes.len() > 16 * 1024 * 1024 - self.0.len() { return Err(std::io::Error::other("output size")); } self.0.extend_from_slice(bytes); Ok(bytes.len()) } fn flush(&mut self) -> std::io::Result<()> { Ok(()) } } let mut output = Output(Vec::with_capacity(128)); if request.uri().path() == "/bench/wire/count" { let arguments: Object = serde_json::from_str(text).map_err(fault)?; serde_json::to_writer( &mut output, &Envelope { code: 0, message: "ok", data: arguments.0.values.0.len() as i64, }, ) .map_err(fault)?; } else { let arguments: Object = serde_json::from_str(text).map_err(fault)?; serde_json::to_writer( &mut output, &Envelope { code: 0, message: "ok", data: arguments.0.payload.0, }, ) .map_err(fault)?; } let mut response = Response::new(output.0.into()); response.headers_mut().insert( hyper::header::CONTENT_TYPE, hyper::header::HeaderValue::from_static("application/json; charset=utf-8"), ); Ok(response.into_body().into()) } fn main() { println!("case,sample,implementation,elapsed_ns,checksum"); let runtime = Runtime::new(Limits { threads: 1, workers: 1, tasks: 8, }) .unwrap(); runtime .run(async |scope| { for size in [64, 4096, 65536] { let payload = Payload { text: "雪\\\"".repeat(size / 5), value: 42, }; let body = format!( "{{\"payload\":{}}}", serde_json::to_string(&payload).unwrap() ) .into_bytes(); let values = [Input { request: hyper::Request::builder() .method("POST") .uri("/bench/wire/echo") .header("content-type", "application/json") .body(body.into()) .unwrap(), peer: ([127, 0, 0, 1], 12345).into(), scope, }]; compare( &format!("http_fixed_record_{size}"), &values, 200, generated, reference, |body| body.len() as u64, ); } for size in [16, 1024, 8192, 32768] { let body = format!("{{\"values\":[{}]}}", vec!["42"; size].join(",")).into_bytes(); let values = [Input { request: hyper::Request::builder() .method("POST") .uri("/bench/wire/count") .header("content-type", "application/json") .body(body.into()) .unwrap(), peer: ([127, 0, 0, 1], 12345).into(), scope, }]; compare( &format!("http_integer_list_{size}"), &values, 200, generated, reference, |body| body.len() as u64, ); } }) .unwrap(); }