From 4f33c2e15909b4c9e3c0e7d90e0bfdff69eb6c77 Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Tue, 13 May 2025 11:08:04 -0400 Subject: [PATCH 01/10] benchmark of ping pong --- sim/benches/ping_pong_bench.rs | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 sim/benches/ping_pong_bench.rs diff --git a/sim/benches/ping_pong_bench.rs b/sim/benches/ping_pong_bench.rs new file mode 100644 index 0000000..4ba5368 --- /dev/null +++ b/sim/benches/ping_pong_bench.rs @@ -0,0 +1,91 @@ +#![feature(test)] + +extern crate test; + + +#[cfg(test)] +mod testy { + use chrono::Local; + use env_logger::{Builder, Env, Target}; + use log::{debug, error, info, LevelFilter}; + use std::io::Write; + + use sim::checker::Checker; + use sim::input_modeling::ContinuousRandomVariable; + use sim::models::{Generator, Model, Processor, Storage}; + use sim::report::Report; + use sim::simulator::{Connector, Message, Simulation}; + use test::Bencher; + + #[bench] + fn ping_pong_bench(b: &mut Bencher) { + let bench_iterations = 5; + + //run the ping pong a bunch of times and collect runtime metrics. + let (initial_messages, mut simulation) = ping_pong_sim(); + + initial_messages.iter().for_each(|m| { + info!("injecting intial messages: {:?}", m); + simulation.inject_input(m.clone()) + }); + + b.iter(|| simulation.step_n(bench_iterations).unwrap()); + } + + fn ping_pong_sim() -> ([Message; 1], Simulation) { + let models = [ + Model::new( + String::from("player-01"), + Box::new(Processor::new( + ContinuousRandomVariable::Exp { lambda: 0.9 }, + None, + String::from("receive"), + String::from("send"), + false, + None, + )), + ), + Model::new( + String::from("player-02"), + Box::new(Processor::new( + ContinuousRandomVariable::Exp { lambda: 0.9 }, + None, + String::from("receive"), + String::from("send"), + false, + None, + )), + ), + ]; + + let connectors = [ + Connector::new( + String::from("p1 to p2"), + String::from("player-01"), + String::from("player-02"), + String::from("send"), + String::from("receive"), + ), + Connector::new( + String::from("p2 to p1"), + String::from("player-02"), + String::from("player-01"), + String::from("send"), + String::from("receive"), + ), + ]; + + let initial_messages = [Message::new( + "manual".to_string(), + "manual".to_string(), + "player-01".to_string(), + "receive".to_string(), + 0.0, + "Ball".to_string(), + )]; + + let simulation = Simulation::post(models.to_vec(), connectors.to_vec()); + (initial_messages, simulation) + } + +} From 93e90e1c10345a449b951b550c0cec83d9a75f31 Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Tue, 13 May 2025 16:04:18 -0400 Subject: [PATCH 02/10] Adding storage benchmark --- sim/benches/ping_pong_bench.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/benches/ping_pong_bench.rs b/sim/benches/ping_pong_bench.rs index 4ba5368..de14354 100644 --- a/sim/benches/ping_pong_bench.rs +++ b/sim/benches/ping_pong_bench.rs @@ -16,7 +16,7 @@ mod testy { use sim::report::Report; use sim::simulator::{Connector, Message, Simulation}; use test::Bencher; - + #[bench] fn ping_pong_bench(b: &mut Bencher) { let bench_iterations = 5; From 8635c0fae092b06b02165bfd1e10ddaa7dc6bc4a Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Tue, 13 May 2025 16:32:12 -0400 Subject: [PATCH 03/10] working example of storage test --- sim/benches/storage_bench.rs | 73 ++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 sim/benches/storage_bench.rs diff --git a/sim/benches/storage_bench.rs b/sim/benches/storage_bench.rs new file mode 100644 index 0000000..522c55d --- /dev/null +++ b/sim/benches/storage_bench.rs @@ -0,0 +1,73 @@ +#![feature(test)] + +extern crate test; + +#[cfg(test)] +mod test_models { + use sim::models::{DevsModel, Model, ModelMessage, Storage}; + use sim::simulator::Services; + use test::Bencher; + + #[bench] + fn storage_bench(b: &mut Bencher) { + let mut model = Model::new( + "bench_storage".to_string(), + Box::new(Storage::new( + "put".to_string(), + "get".to_string(), + "stored".to_string(), + false, + )), + ); + let message = ModelMessage { + port_name: "store".to_string(), + content: "value001".to_string(), + }; + + b.iter(|| { + let mut services = Services::default(); + let ext_result = model.events_int(&mut services); + let int_result = model.events_ext(&message, &mut services); + }); + } + + #[test] + fn storage_test() { + let mut model = Model::new( + "bench_storage".to_string(), + Box::new(Storage::new( + "put".to_string(), + "get".to_string(), + "stored".to_string(), + false, + )), + ); + let message = ModelMessage { + port_name: "put".to_string(), + content: "value001".to_string(), + }; + + let mut services = Services::default(); + let ext_result = model.events_ext(&message, &mut services); + assert!(ext_result.is_ok()); + + let int_results = model.events_int(& mut services); + assert!(int_results.is_ok()); + + let message = ModelMessage { + port_name: "get".to_string(), + content: "ignored".to_string(), + }; + let ext_result = model.events_ext(&message, &mut services); + assert!(ext_result.is_ok()); + + let int_results = model.events_int(& mut services); + assert!(int_results.is_ok()); + + } +} + +// warning: `sim` (bench "storage_bench") generated 2 warnings +// Finished `bench` profile [optimized] target(s) in 0.04s +// Running benches/storage_bench.rs (target/release/deps/storage_bench-016615949a18d51a) +// 26.23022772606383 ns/iter (+/- 0.5808988530585104) From c43df28df66376c1d90ba64b5112271378c23c13 Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Tue, 13 May 2025 17:05:56 -0400 Subject: [PATCH 04/10] Organized storage_bench a little --- sim/benches/storage_bench.rs | 92 ++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/sim/benches/storage_bench.rs b/sim/benches/storage_bench.rs index 522c55d..27c7913 100644 --- a/sim/benches/storage_bench.rs +++ b/sim/benches/storage_bench.rs @@ -7,10 +7,23 @@ mod test_models { use sim::models::{DevsModel, Model, ModelMessage, Storage}; use sim::simulator::Services; use test::Bencher; + use js_sys::Math::exp; - #[bench] - fn storage_bench(b: &mut Bencher) { - let mut model = Model::new( + fn put_message(content: String) -> ModelMessage{ + ModelMessage { + port_name: "put".to_string(), + content: content, + } + } + fn get_message() -> ModelMessage { + ModelMessage { + port_name: "get".to_string(), + content: "NA01".to_string(), + } + } + + fn get_bench_storage() -> Model { + Model::new( "bench_storage".to_string(), Box::new(Storage::new( "put".to_string(), @@ -18,56 +31,53 @@ mod test_models { "stored".to_string(), false, )), - ); - let message = ModelMessage { - port_name: "store".to_string(), - content: "value001".to_string(), - }; - - b.iter(|| { - let mut services = Services::default(); - let ext_result = model.events_int(&mut services); - let int_result = model.events_ext(&message, &mut services); - }); + ) } #[test] + ///verify that the storage model stores and retrieves a stored value. fn storage_test() { - let mut model = Model::new( - "bench_storage".to_string(), - Box::new(Storage::new( - "put".to_string(), - "get".to_string(), - "stored".to_string(), - false, - )), - ); - let message = ModelMessage { - port_name: "put".to_string(), - content: "value001".to_string(), - }; - + let mut model = get_bench_storage(); + let expected_message = "value001".to_string(); + let put_message = put_message(expected_message.clone()); + let get_message = get_message(); let mut services = Services::default(); - let ext_result = model.events_ext(&message, &mut services); + let ext_result = model.events_ext(&put_message, &mut services); assert!(ext_result.is_ok()); let int_results = model.events_int(& mut services); assert!(int_results.is_ok()); - - let message = ModelMessage { - port_name: "get".to_string(), - content: "ignored".to_string(), - }; - let ext_result = model.events_ext(&message, &mut services); + + let ext_result = model.events_ext(&get_message, &mut services); assert!(ext_result.is_ok()); let int_results = model.events_int(& mut services); - assert!(int_results.is_ok()); + match int_results { + Ok(vl) => { + assert_eq!(vl.len(), 1); + assert_eq!(vl[0].content, expected_message.clone()); + }, + Err(_) => assert!(int_results.is_err()) + } + } + + + #[bench] + fn storage_bench(b: &mut Bencher) { + let mut model = get_bench_storage(); + let put_message = put_message("value001".to_string()); + let get_message = get_message(); + + b.iter(|| { + let mut services = Services::default(); + let ext_result = model.events_ext(&put_message, &mut services); + let int_result = model.events_int(&mut services); + let ext_result = model.events_ext(&get_message, &mut services); + let int_result = model.events_int(&mut services); + + }); } +// test test_models::storage_bench ... bench: 165.55 ns/iter (+/- 2.20) +// test test_models::storage_bench ... bench: 165.97 ns/iter (+/- 2.58) } - -// warning: `sim` (bench "storage_bench") generated 2 warnings -// Finished `bench` profile [optimized] target(s) in 0.04s -// Running benches/storage_bench.rs (target/release/deps/storage_bench-016615949a18d51a) -// 26.23022772606383 ns/iter (+/- 0.5808988530585104) From 8d35209a51c26046e328a3260834f168afbbba9d Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Tue, 13 May 2025 19:09:40 -0400 Subject: [PATCH 05/10] loadbalancer tests seem to be working. --- sim/Cargo.toml | 1 + sim/benches/loadbalancer_bench.rs | 67 +++++++++++++++++++++++++++++++ sim/benches/storage_bench.rs | 11 ++--- 3 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 sim/benches/loadbalancer_bench.rs diff --git a/sim/Cargo.toml b/sim/Cargo.toml index b5e23fe..74ea5c9 100644 --- a/sim/Cargo.toml +++ b/sim/Cargo.toml @@ -49,6 +49,7 @@ wee_alloc = { version = "0.4", optional = true } [dev-dependencies] wasm-bindgen-test = "0.3" + [profile.release] # Tell `rustc` to optimize for small code size. opt-level = "s" diff --git a/sim/benches/loadbalancer_bench.rs b/sim/benches/loadbalancer_bench.rs new file mode 100644 index 0000000..bfdd52e --- /dev/null +++ b/sim/benches/loadbalancer_bench.rs @@ -0,0 +1,67 @@ +#![feature(test)] + +extern crate test; + +#[cfg(test)] +mod test_loadbalancer { + use std::collections::HashMap; + use test::Bencher; + use sim::models::{DevsModel, LoadBalancer, Model, ModelMessage}; + use sim::simulator::Services; + use std::collections::HashSet; + use std::iter::FromIterator; + use log::info; + + fn job_message(content: String) -> ModelMessage { + ModelMessage { + port_name: "job".to_string(), + content: content, + } + } + + fn get_loadbalancer() -> (Model,HashSet) { + let fpports = vec!["A".to_string(), + "B".to_string(), + "C".to_string()]; + let fpports_set = HashSet::from_iter(fpports.clone().into_iter()); + (Model::new( + "bench_storage".to_string(), + Box::new(LoadBalancer::new( + "job".to_string(), + fpports, + false, + )) + ), fpports_set) + + } + + #[test] + ///verify that the storage model stores and retrieves a stored value. + fn loadbalancer_test() { + let (mut model, mut expected_port_set) = get_loadbalancer(); + + let expected_message = "value001".to_string(); + let job_message = job_message(expected_message.clone()); + let mut services = Services::default(); + + for i in 0..expected_port_set.len(){ + info!("Checking for each port in round robin {}", i); + + let ext_result = &model.events_ext(&job_message, &mut services); + assert!(ext_result.is_ok()); + //expect an internal message routed to "A" port + let int_results = model.events_int(&mut services); + assert!(int_results.is_ok()); + match int_results { + Ok(vl) => { + assert_eq!(vl.len(), 1); + assert_eq!(vl[0].content, expected_message.clone()); + assert!(expected_port_set.contains(&vl[0].port_name), "The expected port `{}` was not found.", vl[0].port_name); + expected_port_set.remove(&vl[0].port_name); + }, + Err(_) => assert!(int_results.is_err()) + } + } + assert!(expected_port_set.is_empty(),"Not all the ports expected have been used. in round robin."); + } +} \ No newline at end of file diff --git a/sim/benches/storage_bench.rs b/sim/benches/storage_bench.rs index 27c7913..07865b0 100644 --- a/sim/benches/storage_bench.rs +++ b/sim/benches/storage_bench.rs @@ -7,8 +7,7 @@ mod test_models { use sim::models::{DevsModel, Model, ModelMessage, Storage}; use sim::simulator::Services; use test::Bencher; - use js_sys::Math::exp; - + fn put_message(content: String) -> ModelMessage{ ModelMessage { port_name: "put".to_string(), @@ -22,7 +21,7 @@ mod test_models { } } - fn get_bench_storage() -> Model { + fn get_storage() -> Model { Model::new( "bench_storage".to_string(), Box::new(Storage::new( @@ -37,7 +36,7 @@ mod test_models { #[test] ///verify that the storage model stores and retrieves a stored value. fn storage_test() { - let mut model = get_bench_storage(); + let mut model = get_storage(); let expected_message = "value001".to_string(); let put_message = put_message(expected_message.clone()); let get_message = get_message(); @@ -59,12 +58,14 @@ mod test_models { }, Err(_) => assert!(int_results.is_err()) } + assert_eq!(services.global_time(), 0f64) + } #[bench] fn storage_bench(b: &mut Bencher) { - let mut model = get_bench_storage(); + let mut model = get_storage(); let put_message = put_message("value001".to_string()); let get_message = get_message(); From 81c044111630e844310eb8ea709f55e654e33c9f Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Tue, 13 May 2025 19:16:17 -0400 Subject: [PATCH 06/10] added bench and example run duration. --- sim/benches/loadbalancer_bench.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sim/benches/loadbalancer_bench.rs b/sim/benches/loadbalancer_bench.rs index bfdd52e..9409498 100644 --- a/sim/benches/loadbalancer_bench.rs +++ b/sim/benches/loadbalancer_bench.rs @@ -64,4 +64,21 @@ mod test_loadbalancer { } assert!(expected_port_set.is_empty(),"Not all the ports expected have been used. in round robin."); } + + #[bench] + fn loadbalancer_bench(b: &mut Bencher) { + let (mut model, mut expected_port_set) = get_loadbalancer(); + + let expected_message = "value001".to_string(); + let job_message = job_message(expected_message.clone()); + let mut services = Services::default(); + + b.iter(|| { + for i in 0..expected_port_set.len() { + let ext_result = &model.events_ext(&job_message, &mut services); + let int_result = model.events_int(&mut services); + } + }); + } + // test test_loadbalancer::loadbalancer_bench ... bench: 549.13 ns/iter (+/- 6.46) } \ No newline at end of file From e54319426ef1c50bedb956e07db68c905cbecf66 Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Wed, 14 May 2025 11:55:17 -0400 Subject: [PATCH 07/10] loadbalancer and storage tests with benchmark --- sim/benches/loadbalancer_bench.rs | 5 +---- sim/benches/ping_pong_bench.rs | 21 ++++++--------------- sim/benches/storage_bench.rs | 3 ++- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/sim/benches/loadbalancer_bench.rs b/sim/benches/loadbalancer_bench.rs index 9409498..1e791bf 100644 --- a/sim/benches/loadbalancer_bench.rs +++ b/sim/benches/loadbalancer_bench.rs @@ -4,13 +4,11 @@ extern crate test; #[cfg(test)] mod test_loadbalancer { - use std::collections::HashMap; use test::Bencher; use sim::models::{DevsModel, LoadBalancer, Model, ModelMessage}; use sim::simulator::Services; use std::collections::HashSet; use std::iter::FromIterator; - use log::info; fn job_message(content: String) -> ModelMessage { ModelMessage { @@ -45,8 +43,6 @@ mod test_loadbalancer { let mut services = Services::default(); for i in 0..expected_port_set.len(){ - info!("Checking for each port in round robin {}", i); - let ext_result = &model.events_ext(&job_message, &mut services); assert!(ext_result.is_ok()); //expect an internal message routed to "A" port @@ -81,4 +77,5 @@ mod test_loadbalancer { }); } // test test_loadbalancer::loadbalancer_bench ... bench: 549.13 ns/iter (+/- 6.46) + // test test_loadbalancer::loadbalancer_bench ... bench: 583.14 ns/iter (+/- 5.70) } \ No newline at end of file diff --git a/sim/benches/ping_pong_bench.rs b/sim/benches/ping_pong_bench.rs index de14354..5abae57 100644 --- a/sim/benches/ping_pong_bench.rs +++ b/sim/benches/ping_pong_bench.rs @@ -2,21 +2,13 @@ extern crate test; - #[cfg(test)] mod testy { - use chrono::Local; - use env_logger::{Builder, Env, Target}; - use log::{debug, error, info, LevelFilter}; - use std::io::Write; - - use sim::checker::Checker; use sim::input_modeling::ContinuousRandomVariable; - use sim::models::{Generator, Model, Processor, Storage}; - use sim::report::Report; + use sim::models::{Model, Processor}; use sim::simulator::{Connector, Message, Simulation}; use test::Bencher; - + #[bench] fn ping_pong_bench(b: &mut Bencher) { let bench_iterations = 5; @@ -24,10 +16,9 @@ mod testy { //run the ping pong a bunch of times and collect runtime metrics. let (initial_messages, mut simulation) = ping_pong_sim(); - initial_messages.iter().for_each(|m| { - info!("injecting intial messages: {:?}", m); - simulation.inject_input(m.clone()) - }); + initial_messages + .iter() + .for_each(|m| simulation.inject_input(m.clone())); b.iter(|| simulation.step_n(bench_iterations).unwrap()); } @@ -87,5 +78,5 @@ mod testy { let simulation = Simulation::post(models.to_vec(), connectors.to_vec()); (initial_messages, simulation) } - + // test testy::ping_pong_bench ... bench: 2,321.04 ns/iter (+/- 22.68) } diff --git a/sim/benches/storage_bench.rs b/sim/benches/storage_bench.rs index 07865b0..3a2e505 100644 --- a/sim/benches/storage_bench.rs +++ b/sim/benches/storage_bench.rs @@ -80,5 +80,6 @@ mod test_models { }); } // test test_models::storage_bench ... bench: 165.55 ns/iter (+/- 2.20) -// test test_models::storage_bench ... bench: 165.97 ns/iter (+/- 2.58) +// test test_models::storage_bench ... bench: 165.97 ns/iter (+/- 2.58) +// test test_models::storage_bench ... bench: 166.18 ns/iter (+/- 3.14) } From d79f6eb1fc38cd3f4c04a1ed647c36c136aee2db Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Wed, 14 May 2025 12:13:24 -0400 Subject: [PATCH 08/10] revert unexpected change in Cargo.toml --- sim/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/sim/Cargo.toml b/sim/Cargo.toml index 74ea5c9..b5e23fe 100644 --- a/sim/Cargo.toml +++ b/sim/Cargo.toml @@ -49,7 +49,6 @@ wee_alloc = { version = "0.4", optional = true } [dev-dependencies] wasm-bindgen-test = "0.3" - [profile.release] # Tell `rustc` to optimize for small code size. opt-level = "s" From 21976f0c7f04cd632fb0c0222f3e692c0cbbf847 Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Thu, 15 May 2025 14:23:30 -0400 Subject: [PATCH 09/10] Clean up warnings and added parallel_gateway fan-out & fan-in test and benchmark. --- sim/benches/fan_out_fan_in_bench.rs | 130 ++++++++++++++++++++++++++++ sim/benches/loadbalancer_bench.rs | 10 +-- sim/benches/storage_bench.rs | 8 +- 3 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 sim/benches/fan_out_fan_in_bench.rs diff --git a/sim/benches/fan_out_fan_in_bench.rs b/sim/benches/fan_out_fan_in_bench.rs new file mode 100644 index 0000000..3932aac --- /dev/null +++ b/sim/benches/fan_out_fan_in_bench.rs @@ -0,0 +1,130 @@ +// Fan a single message out to N processors and then join them all back. +// benchmark execution time (not simulation time) + +#![feature(test)] + +extern crate test; + +#[cfg(test)] +mod test_parallel_gateway { + use sim::models::{Model, ParallelGateway}; + use sim::simulator::{Connector, Message, Simulation}; + use test::Bencher; + + /// the message that will be sent. + fn initial_message(content: String) -> Message { + Message::new( + "manual".to_string(), + "manual".to_string(), + "PG_FAN_OUT".to_string(), + "IN".to_string(), + 0.0, + content, + ) + } + + fn get_out_port_names(port_count: usize) -> Vec { + (0..port_count).map(|s| format!("OUT_{}", s)).collect() + } + fn get_in_port_names(port_count: usize) -> Vec { + (0..port_count).map(|s| format!("IN_{}", s)).collect() + } + + fn get_parallel_gateway_fan_out(port_count: usize) -> Model { + Model::new( + "PG_FAN_OUT".to_string(), + Box::new(ParallelGateway::new( + vec!["IN".to_string()], + get_out_port_names(port_count), + false, + )), + ) + } + + fn get_parallel_gateway_fan_in(port_count: usize) -> Model { + Model::new( + "PG_FAN_IN".to_string(), + Box::new(ParallelGateway::new( + get_in_port_names(port_count), + vec!["OUT".to_string()], + false, + )), + ) + } + fn get_models(port_count: usize) -> Vec { + vec![ + get_parallel_gateway_fan_out(port_count), + get_parallel_gateway_fan_in(port_count), + ] + } + + fn get_connectors(port_count: usize) -> Vec { + //Connect OUT_0 to IN_0 + (0..port_count) + .map(|pi| { + Connector::new( + format!("connector_{}", pi), + "PG_FAN_OUT".to_string(), + "PG_FAN_IN".to_string(), + format!("OUT_{}", pi), + format!("IN_{}", pi), + ) + }) + .collect() + } + + fn get_simulator(port_count: usize) -> Simulation { + Simulation::post(get_models(port_count), get_connectors(port_count)) + } + + #[test] + fn fi_fo_test() { + let fan_size = 10usize; + let mut sim = get_simulator(fan_size); + sim.inject_input(initial_message("TESTING".to_string())); + let result = sim.step(); + assert!(result.is_ok()); + assert_eq!(result.unwrap().len(), fan_size); + } + + #[bench] + fn fi_fo_bench_100(b: &mut Bencher) { + let fan_size = 100usize; + let mut sim = get_simulator(fan_size); + sim.inject_input(initial_message("TESTING".to_string())); + b.iter(|| sim.step()); + } + #[bench] + fn fi_fo_bench_1000(b: &mut Bencher) { + let fan_size = 10000usize; + let mut sim = get_simulator(fan_size); + sim.inject_input(initial_message("TESTING".to_string())); + b.iter(|| sim.step()); + } + #[bench] + fn fi_fo_bench_50000(b: &mut Bencher) { + let fan_size = 50000usize; + let mut sim = get_simulator(fan_size); + sim.inject_input(initial_message("TESTING".to_string())); + b.iter(|| sim.step()); + } + + #[bench] + fn fi_fo_bench_80000(b: &mut Bencher) { + let fan_size = 80000usize; + let mut sim = get_simulator(fan_size); + sim.inject_input(initial_message("TESTING".to_string())); + b.iter(|| sim.step()); + } + // test test_parallel_gateway::fi_fo_bench_100 ... bench: 47.90 ns/iter (+/- 0.21) + // test test_parallel_gateway::fi_fo_bench_1000 ... bench: 55.22 ns/iter (+/- 0.35) + + // test test_parallel_gateway::fi_fo_bench_100 ... bench: 47.90 ns/iter (+/- 0.56) + // test test_parallel_gateway::fi_fo_bench_1000 ... bench: 55.53 ns/iter (+/- 4.41) + // test test_parallel_gateway::fi_fo_bench_50000 ... bench: 59.44 ns/iter (+/- 1.39) + + // test test_parallel_gateway::fi_fo_bench_100 ... bench: 48.24 ns/iter (+/- 2.12) + // test test_parallel_gateway::fi_fo_bench_1000 ... bench: 50.00 ns/iter (+/- 8.31) + // test test_parallel_gateway::fi_fo_bench_50000 ... bench: 59.83 ns/iter (+/- 5.48) + // test test_parallel_gateway::fi_fo_bench_80000 ... bench: 58.30 ns/iter (+/- 8.40) +} diff --git a/sim/benches/loadbalancer_bench.rs b/sim/benches/loadbalancer_bench.rs index 1e791bf..cb00b6d 100644 --- a/sim/benches/loadbalancer_bench.rs +++ b/sim/benches/loadbalancer_bench.rs @@ -42,7 +42,7 @@ mod test_loadbalancer { let job_message = job_message(expected_message.clone()); let mut services = Services::default(); - for i in 0..expected_port_set.len(){ + for _ in 0..expected_port_set.len(){ let ext_result = &model.events_ext(&job_message, &mut services); assert!(ext_result.is_ok()); //expect an internal message routed to "A" port @@ -63,16 +63,16 @@ mod test_loadbalancer { #[bench] fn loadbalancer_bench(b: &mut Bencher) { - let (mut model, mut expected_port_set) = get_loadbalancer(); + let (mut model, expected_port_set) = get_loadbalancer(); let expected_message = "value001".to_string(); let job_message = job_message(expected_message.clone()); let mut services = Services::default(); b.iter(|| { - for i in 0..expected_port_set.len() { - let ext_result = &model.events_ext(&job_message, &mut services); - let int_result = model.events_int(&mut services); + for _ in 0..expected_port_set.len() { + let _ = &model.events_ext(&job_message, &mut services); + let _ = model.events_int(&mut services); } }); } diff --git a/sim/benches/storage_bench.rs b/sim/benches/storage_bench.rs index 3a2e505..da53010 100644 --- a/sim/benches/storage_bench.rs +++ b/sim/benches/storage_bench.rs @@ -72,10 +72,10 @@ mod test_models { b.iter(|| { let mut services = Services::default(); - let ext_result = model.events_ext(&put_message, &mut services); - let int_result = model.events_int(&mut services); - let ext_result = model.events_ext(&get_message, &mut services); - let int_result = model.events_int(&mut services); + let _ = model.events_ext(&put_message, &mut services); + let _ = model.events_int(&mut services); + let _ = model.events_ext(&get_message, &mut services); + let _ = model.events_int(&mut services); }); } From 668a856d0c971fa5451d95b3679cce08334fc942 Mon Sep 17 00:00:00 2001 From: "Bruce W. Lowther" Date: Thu, 22 May 2025 16:27:28 -0400 Subject: [PATCH 10/10] Clean up warnings and added parallel_gateway fan-out & fan-in test and benchmark. --- sim/benches/fan_out_fan_in_bench.rs | 107 +++++++++++++++++++++++++--- sim/src/models/parallel_gateway.rs | 1 + 2 files changed, 97 insertions(+), 11 deletions(-) diff --git a/sim/benches/fan_out_fan_in_bench.rs b/sim/benches/fan_out_fan_in_bench.rs index 3932aac..0cb65d4 100644 --- a/sim/benches/fan_out_fan_in_bench.rs +++ b/sim/benches/fan_out_fan_in_bench.rs @@ -7,8 +7,9 @@ extern crate test; #[cfg(test)] mod test_parallel_gateway { - use sim::models::{Model, ParallelGateway}; - use sim::simulator::{Connector, Message, Simulation}; + use sim::models::{DevsModel, Model, ModelMessage, ParallelGateway}; + use sim::simulator::{Connector, Message, Services, Simulation}; + use sim::utils::errors::SimulationError; use test::Bencher; /// the message that will be sent. @@ -108,23 +109,107 @@ mod test_parallel_gateway { sim.inject_input(initial_message("TESTING".to_string())); b.iter(|| sim.step()); } + + // #[bench] + // fn fi_fo_bench_80000(b: &mut Bencher) { + // let fan_size = 80000usize; + // let mut sim = get_simulator(fan_size); + // sim.inject_input(initial_message("TESTING".to_string())); + // b.iter(|| sim.step()); + // } - #[bench] - fn fi_fo_bench_80000(b: &mut Bencher) { - let fan_size = 80000usize; - let mut sim = get_simulator(fan_size); - sim.inject_input(initial_message("TESTING".to_string())); - b.iter(|| sim.step()); - } // test test_parallel_gateway::fi_fo_bench_100 ... bench: 47.90 ns/iter (+/- 0.21) // test test_parallel_gateway::fi_fo_bench_1000 ... bench: 55.22 ns/iter (+/- 0.35) - + // test test_parallel_gateway::fi_fo_bench_100 ... bench: 47.90 ns/iter (+/- 0.56) // test test_parallel_gateway::fi_fo_bench_1000 ... bench: 55.53 ns/iter (+/- 4.41) // test test_parallel_gateway::fi_fo_bench_50000 ... bench: 59.44 ns/iter (+/- 1.39) - + // test test_parallel_gateway::fi_fo_bench_100 ... bench: 48.24 ns/iter (+/- 2.12) // test test_parallel_gateway::fi_fo_bench_1000 ... bench: 50.00 ns/iter (+/- 8.31) // test test_parallel_gateway::fi_fo_bench_50000 ... bench: 59.83 ns/iter (+/- 5.48) // test test_parallel_gateway::fi_fo_bench_80000 ... bench: 58.30 ns/iter (+/- 8.40) + + #[test] + fn fo_test() { + let fan_size = 10000usize; + let mut model = + ParallelGateway::new(vec!["IN".to_string()], get_out_port_names(fan_size), false); + let in_message = ModelMessage { + port_name: "IN".to_string(), + content: "testing".to_string(), + }; + + let mut services = Services::default(); + + let ext_result = &model.events_ext(&in_message, &mut services); + assert!(ext_result.is_ok()); + let int_results = model.events_int(&mut services); + assert!(int_results.is_ok()); + assert_eq!(int_results.unwrap().len(), fan_size); + + //instantaneous operation in simulation + assert_eq!(services.global_time(), 0.0f64); + } + #[test] + fn fi_test() { + let fan_size = 10000usize; + let mut model = + ParallelGateway::new(get_in_port_names(fan_size), vec!["OUT".to_string()], false); + let in_messages: Vec = (0..fan_size) + .map(|i| ModelMessage { + port_name: format!("IN_{}", i), + content: "testing".to_string(), + }) + .collect(); + + let mut services = Services::default(); + + let ext_results: Vec> = in_messages + .iter() + .map(|i| model.events_ext(i, &mut services)) + .collect(); + + assert!(ext_results.iter().all(|r| r.is_ok())); + //instantaneous simulation time. + assert_eq!(services.global_time(), 0.0f64); + + //There's only one resulting message. This is a fan in. + let int_results = model.events_int(&mut services); + assert!(int_results.is_ok()); + let mm = &int_results.unwrap().pop().unwrap(); + assert_eq!(mm.port_name, "OUT".to_string()); + + //nothing left after the previous events_int call. + let int_results = model.events_int(&mut services); + assert!(int_results.is_ok()); + assert!(int_results.unwrap().is_empty()); + } + + + // TODO do fo_bench + // TODO smaller fan size for benchmark tests. + #[bench] + fn fi_bench(b: &mut Bencher) { + let fan_size = 10000usize; + let mut model = + ParallelGateway::new(get_in_port_names(fan_size), vec!["OUT".to_string()], false); + let in_messages: Vec = (0..fan_size) + .map(|i| ModelMessage { + port_name: format!("IN_{}", i), + content: "testing".to_string(), + }) + .collect(); + + let mut services = Services::default(); + + //Todo m + b.iter(|| { + let _: Vec> = in_messages + .iter() + .map(|i| model.events_ext(i, &mut services)) + .collect(); + let _ = model.events_int(&mut services); + }); + } } diff --git a/sim/src/models/parallel_gateway.rs b/sim/src/models/parallel_gateway.rs index dca0436..cb62710 100644 --- a/sim/src/models/parallel_gateway.rs +++ b/sim/src/models/parallel_gateway.rs @@ -97,6 +97,7 @@ impl ParallelGateway { .find(|(_, count)| **count == self.ports_in.flow_paths.len()) } + /// ModelMessages are stored by content in a bag. fn increment_collection(&mut self, incoming_message: &ModelMessage, services: &mut Services) { *self .state