diff --git a/examples/protocol/bench/support/bench_common.rs b/examples/protocol/bench/support/bench_common.rs index d581e42..e2a7393 100644 --- a/examples/protocol/bench/support/bench_common.rs +++ b/examples/protocol/bench/support/bench_common.rs @@ -72,142 +72,171 @@ pub fn run_decode_call(iterations: usize) -> usize { #[inline(never)] pub fn run_forward_call_receive(iterations: usize) -> usize { - let mut checksum = 0usize; - for _ in 0..iterations { - let mut root = ProtocolEndpoint::new( - Vec::new(), - None, - vec![ChildRoute::registered(path(&["edge"]))], - Vec::new(), - ); - let hook_id = root.allocate_hook_id(); - let frame = root - .make_call( - path(&["edge", "worker"]), - Some(String::from("service")), - String::from("example.service.v1.invoke"), - Some(hook_id), - vec![1; 32], - ) - .expect("seed call should encode"); - + let cases = build_forward_call_cases(iterations); + run_cases(cases, |(mut root, frame)| { let outcome = root .receive(&Ingress::Local, frame) .expect("forward receive should work"); - let forwarded = match outcome { - EndpointOutcome::Forward { route, frame } => route_value(route).wrapping_add(frame.len()), + match outcome { + EndpointOutcome::Forward { route, frame } => { + route_value(route).wrapping_add(frame.len()) + } EndpointOutcome::Local(_) => 0, EndpointOutcome::Dropped => usize::from(true), - }; - checksum = checksum.wrapping_add(forwarded); - } - black_box(checksum) + } + }) } #[inline(never)] pub fn run_local_call_receive(iterations: usize) -> usize { - let mut checksum = 0usize; - for _ in 0..iterations { - let mut endpoint = ProtocolEndpoint::new( - path(&["worker"]), - Some(Vec::new()), - Vec::new(), - vec![LeafSpec { - name: String::from("service"), - procedures: vec![String::from("example.service.v1.invoke")], - }], - ); - let frame = encode_packet( - &PacketHeader { - packet_type: PacketType::Call, - src_path: Vec::new(), - dst_path: path(&["worker"]), - dst_leaf: Some(String::from("service")), - hook_id: None, - }, - &CallMessage { - procedure_id: String::from("example.service.v1.invoke"), - data: vec![2; 32], - response_hook: Some(unshell::protocol::HookTarget { - hook_id: 42, - return_path: Vec::new(), - }), - }, - ) - .expect("seed local call should encode"); - + let cases = build_local_call_cases(iterations); + run_cases(cases, |(mut endpoint, frame)| { let outcome = endpoint .receive(&Ingress::Parent, frame) .expect("local call should work"); match outcome { - EndpointOutcome::Local(LocalEvent::Call { header, message }) => { - checksum = checksum - .wrapping_add(header.dst_path.len()) - .wrapping_add(header.src_path.len()) - .wrapping_add(header.dst_leaf.as_ref().map_or(0, String::len)) - .wrapping_add(message.data.len()) - .wrapping_add(message.procedure_id.len()); - } + EndpointOutcome::Local(LocalEvent::Call { header, message }) => header + .dst_path + .len() + .wrapping_add(header.src_path.len()) + .wrapping_add(header.dst_leaf.as_ref().map_or(0, String::len)) + .wrapping_add(message.data.len()) + .wrapping_add(message.procedure_id.len()), other => panic!("expected local call event, got {other:?}"), } - } - black_box(checksum) + }) } #[inline(never)] pub fn run_hook_data_receive(iterations: usize) -> usize { - let mut checksum = 0usize; - for _ in 0..iterations { - let mut host = ProtocolEndpoint::new( - Vec::new(), - None, - vec![ChildRoute::registered(path(&["worker"]))], - Vec::new(), - ); - let hook_id = host.allocate_hook_id(); - host.make_call( - path(&["worker"]), - None, - String::from("example.service.v1.invoke"), - Some(hook_id), - vec![3; 8], - ) - .expect("seed active hook should encode"); - let frame = encode_packet( - &PacketHeader { - packet_type: PacketType::Data, - src_path: path(&["worker"]), - dst_path: Vec::new(), - dst_leaf: None, - hook_id: Some(hook_id), - }, - &unshell::protocol::DataMessage { - procedure_id: String::from("example.service.v1.invoke"), - data: vec![4; 16], - end_hook: false, - }, - ) - .expect("seed data should encode"); - + let cases = build_hook_data_cases(iterations); + run_cases(cases, |(mut host, frame)| { let outcome = host .receive(&Ingress::Child(path(&["worker"])), frame) .expect("hook data should work"); match outcome { EndpointOutcome::Local(LocalEvent::Data { header, message, .. - }) => { - checksum = checksum - .wrapping_add(header.hook_id.unwrap_or_default() as usize) - .wrapping_add(message.data.len()) - .wrapping_add(message.procedure_id.len()) - .wrapping_add(message.end_hook as usize); - } + }) => (header.hook_id.unwrap_or_default() as usize) + .wrapping_add(message.data.len()) + .wrapping_add(message.procedure_id.len()) + .wrapping_add(message.end_hook as usize), other => panic!("expected local data event, got {other:?}"), } + }) +} + +fn run_cases(cases: Vec, mut op: impl FnMut(T) -> usize) -> usize { + let mut checksum = 0usize; + for case in cases { + checksum = checksum.wrapping_add(op(case)); } black_box(checksum) } +fn build_forward_call_cases( + iterations: usize, +) -> Vec<(ProtocolEndpoint, unshell::protocol::FrameBytes)> { + (0..iterations) + .map(|_| { + let mut root = ProtocolEndpoint::new( + Vec::new(), + None, + vec![ChildRoute::registered(path(&["edge"]))], + Vec::new(), + ); + let hook_id = root.allocate_hook_id(); + let frame = root + .make_call( + path(&["edge", "worker"]), + Some(String::from("service")), + String::from("example.service.v1.invoke"), + Some(hook_id), + vec![1; 32], + ) + .expect("seed call should encode"); + (root, frame) + }) + .collect() +} + +fn build_local_call_cases( + iterations: usize, +) -> Vec<(ProtocolEndpoint, unshell::protocol::FrameBytes)> { + (0..iterations) + .map(|_| { + let endpoint = ProtocolEndpoint::new( + path(&["worker"]), + Some(Vec::new()), + Vec::new(), + vec![LeafSpec { + name: String::from("service"), + procedures: vec![String::from("example.service.v1.invoke")], + }], + ); + let frame = encode_packet( + &PacketHeader { + packet_type: PacketType::Call, + src_path: Vec::new(), + dst_path: path(&["worker"]), + dst_leaf: Some(String::from("service")), + hook_id: None, + }, + &CallMessage { + procedure_id: String::from("example.service.v1.invoke"), + data: vec![2; 32], + response_hook: Some(unshell::protocol::HookTarget { + hook_id: 42, + return_path: Vec::new(), + }), + }, + ) + .expect("seed local call should encode"); + (endpoint, frame) + }) + .collect() +} + +fn build_hook_data_cases( + iterations: usize, +) -> Vec<(ProtocolEndpoint, unshell::protocol::FrameBytes)> { + (0..iterations) + .map(|_| { + let mut host = ProtocolEndpoint::new( + Vec::new(), + None, + vec![ChildRoute::registered(path(&["worker"]))], + Vec::new(), + ); + let hook_id = host.allocate_hook_id(); + host.make_call( + path(&["worker"]), + None, + String::from("example.service.v1.invoke"), + Some(hook_id), + vec![3; 8], + ) + .expect("seed active hook should encode"); + let frame = encode_packet( + &PacketHeader { + packet_type: PacketType::Data, + src_path: path(&["worker"]), + dst_path: Vec::new(), + dst_leaf: None, + hook_id: Some(hook_id), + }, + &unshell::protocol::DataMessage { + procedure_id: String::from("example.service.v1.invoke"), + data: vec![4; 16], + end_hook: false, + }, + ) + .expect("seed data should encode"); + (host, frame) + }) + .collect() +} + pub fn path(parts: &[&str]) -> Vec { parts.iter().map(|part| String::from(*part)).collect() }