From 6f86accd0a56d6dba2ac676a36acd4bf2c68b4e0 Mon Sep 17 00:00:00 2001 From: Robert Jacobson Date: Mon, 3 Feb 2025 16:59:02 -0600 Subject: [PATCH] Made basic-infection and births-deaths into libraries so they could share code with the benchmarks. --- .gitignore | 2 +- Cargo.toml | 10 +++++ benches/README.md | 20 +++++---- .../example_basic_infection.rs | 7 ++-- .../incidence_report.rs | 1 - .../infection_manager.rs | 1 - benches/example_basic_infection/people.rs | 1 - .../transmission_manager.rs | 1 - .../demographics_report.rs | 1 - .../example_births_deaths.rs | 13 +++--- .../example_births_deaths/incidence_report.rs | 1 - .../infection_manager.rs | 1 - benches/example_births_deaths/input.json | 16 ++++++- .../parameters_loader.rs | 1 - .../population_manager.rs | 1 - .../transmission_manager.rs | 1 - criterion.toml | 2 +- examples/basic-infection/Cargo.toml | 21 ++++++++++ examples/basic-infection/main.rs | 31 +------------- .../{ => src}/incidence_report.rs | 2 +- .../{ => src}/infection_manager.rs | 0 examples/basic-infection/src/lib.rs | 30 +++++++++++++ examples/basic-infection/{ => src}/people.rs | 0 .../{ => src}/transmission_manager.rs | 0 examples/births-deaths/Cargo.toml | 22 ++++++++++ examples/births-deaths/main.rs | 42 +------------------ .../{ => src}/demographics_report.rs | 4 +- .../{ => src}/incidence_report.rs | 1 + .../{ => src}/infection_manager.rs | 0 examples/births-deaths/src/lib.rs | 40 ++++++++++++++++++ .../{ => src}/parameters_loader.rs | 0 .../{ => src}/population_manager.rs | 0 .../{ => src}/transmission_manager.rs | 0 33 files changed, 167 insertions(+), 106 deletions(-) delete mode 120000 benches/example_basic_infection/incidence_report.rs delete mode 120000 benches/example_basic_infection/infection_manager.rs delete mode 120000 benches/example_basic_infection/people.rs delete mode 120000 benches/example_basic_infection/transmission_manager.rs delete mode 120000 benches/example_births_deaths/demographics_report.rs delete mode 120000 benches/example_births_deaths/incidence_report.rs delete mode 120000 benches/example_births_deaths/infection_manager.rs mode change 120000 => 100644 benches/example_births_deaths/input.json delete mode 120000 benches/example_births_deaths/parameters_loader.rs delete mode 120000 benches/example_births_deaths/population_manager.rs delete mode 120000 benches/example_births_deaths/transmission_manager.rs create mode 100644 examples/basic-infection/Cargo.toml rename examples/basic-infection/{ => src}/incidence_report.rs (95%) rename examples/basic-infection/{ => src}/infection_manager.rs (100%) create mode 100644 examples/basic-infection/src/lib.rs rename examples/basic-infection/{ => src}/people.rs (100%) rename examples/basic-infection/{ => src}/transmission_manager.rs (100%) create mode 100644 examples/births-deaths/Cargo.toml rename examples/births-deaths/{ => src}/demographics_report.rs (97%) rename examples/births-deaths/{ => src}/incidence_report.rs (97%) rename examples/births-deaths/{ => src}/infection_manager.rs (100%) create mode 100644 examples/births-deaths/src/lib.rs rename examples/births-deaths/{ => src}/parameters_loader.rs (100%) rename examples/births-deaths/{ => src}/population_manager.rs (100%) rename examples/births-deaths/{ => src}/transmission_manager.rs (100%) diff --git a/.gitignore b/.gitignore index d4a20e7e..1773f07d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ profile.json # Generated by Cargo # will have compiled files and executables debug/ -target/ +**/target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/Cargo.toml b/Cargo.toml index fd9652da..d859426b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,11 @@ rand_distr = "^0.4.3" tempfile = "^3.15.0" ordered-float = "^4.6.0" assert_cmd = "^2.0.16" +criterion = "^0.5.1" + +# Example Libraries +ixa_example_basic_infection = { path = "examples/basic-infection" } +ixa_example_births_deaths = { path = "examples/births-deaths" } [lints.clippy] pedantic = { level = "warn", priority = -1 } @@ -47,6 +52,11 @@ path = "tests/bin/runner_test_custom_args.rs" name = "runner_test_debug" path = "tests/bin/runner_test_debug.rs" +[[bench]] +name = "example_basic_infection" +path = "benches/example_basic_infection/example_basic_infection.rs" +harness = false + [[bench]] name = "example_births_deaths" path = "benches/example_births_deaths/example_births_deaths.rs" diff --git a/benches/README.md b/benches/README.md index 81c35591..b8655684 100644 --- a/benches/README.md +++ b/benches/README.md @@ -4,7 +4,8 @@ For general Rust profiling information, see: https://nnethercote.github.io/perf- # Generating Flamegraphs -You can use `samply` (Linux and macOS) to capture stack samples from your application and generate a flamegraph, helping you quickly identify and analyze performance hotspots. +You can use `samply` (Linux and macOS) to capture stack samples from your application and generate +a flamegraph, helping you quickly identify and analyze performance hotspots. ## Prerequisites @@ -36,10 +37,10 @@ cargo build --example basic-infection --release && samply record -- target/relea When it completes, `samply` will automatically open a browser with the generated report. - ## `flamegraph` Alternative -You can use `flamegraph` if you prefer. It requires root privileges, but don't use `sudo cargo...`. Do this: +You can use `flamegraph` if you prefer. It requires root privileges, but don't use +`sudo cargo...`. Do this: ```bash cargo flamegraph --root --example basic-infection @@ -49,12 +50,16 @@ This will generate an SVG of the flamegraph in the current directory. # Benchmarking Ixa -Ixa uses [Criterion.rs](https://bheisler.github.io/criterion.rs/book/index.html) for statistical benchmarking. +Ixa uses [Criterion.rs](https://bheisler.github.io/criterion.rs/book/index.html) for statistical +benchmarking. ## Optional Prerequisites - - [`gnuplot`](http://www.gnuplot.info/): The [plotters crate](https://github.com/38/plotters) will be used as a fallback if `gnuplot` is not found. - - [cargo-criterion](https://bheisler.github.io/criterion.rs/book/cargo_criterion/cargo_criterion.html): This is the upcoming "next generation" of Criterion.rs. Eventually it will reduce compilation times and offer more features, but for now it only has feature parity. +- [`gnuplot`](http://www.gnuplot.info/): The [plotters crate](https://github.com/38/plotters) will + be used as a fallback if `gnuplot` is not found. +- [cargo-criterion](https://bheisler.github.io/criterion.rs/book/cargo_criterion/cargo_criterion.html): + This is the upcoming "next generation" of Criterion.rs. Eventually it will reduce compilation + times and offer more features, but for now it only has feature parity. ```bash cargo install cargo-criterion @@ -110,4 +115,5 @@ An HTML report is created at `target/criterion/report/index.html`. On macOS: open target/criterion/report/index.html ``` -On Linux platforms, replace `open` with `xdg-open`, `gnome-open`, or `kde-open`, depending on your system configuration, or just open the file in a browser. +On Linux platforms, replace `open` with `xdg-open`, `gnome-open`, or `kde-open`, depending on your +system configuration, or just open the file in a browser. diff --git a/benches/example_basic_infection/example_basic_infection.rs b/benches/example_basic_infection/example_basic_infection.rs index 878b3513..94cc1383 100644 --- a/benches/example_basic_infection/example_basic_infection.rs +++ b/benches/example_basic_infection/example_basic_infection.rs @@ -2,10 +2,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use ixa::context::Context; use ixa::random::ContextRandomExt; -mod incidence_report; -mod infection_manager; -mod people; -mod transmission_manager; +use ixa_example_basic_infection::{ + incidence_report, infection_manager, people, transmission_manager, +}; static POPULATION: u64 = 1000; static SEED: u64 = 123; diff --git a/benches/example_basic_infection/incidence_report.rs b/benches/example_basic_infection/incidence_report.rs deleted file mode 120000 index 33d07531..00000000 --- a/benches/example_basic_infection/incidence_report.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/basic-infection/incidence_report.rs \ No newline at end of file diff --git a/benches/example_basic_infection/infection_manager.rs b/benches/example_basic_infection/infection_manager.rs deleted file mode 120000 index fd5ea5c7..00000000 --- a/benches/example_basic_infection/infection_manager.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/basic-infection/infection_manager.rs \ No newline at end of file diff --git a/benches/example_basic_infection/people.rs b/benches/example_basic_infection/people.rs deleted file mode 120000 index da034c55..00000000 --- a/benches/example_basic_infection/people.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/basic-infection/people.rs \ No newline at end of file diff --git a/benches/example_basic_infection/transmission_manager.rs b/benches/example_basic_infection/transmission_manager.rs deleted file mode 120000 index ea7ac125..00000000 --- a/benches/example_basic_infection/transmission_manager.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/basic-infection/transmission_manager.rs \ No newline at end of file diff --git a/benches/example_births_deaths/demographics_report.rs b/benches/example_births_deaths/demographics_report.rs deleted file mode 120000 index 708507c5..00000000 --- a/benches/example_births_deaths/demographics_report.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/demographics_report.rs \ No newline at end of file diff --git a/benches/example_births_deaths/example_births_deaths.rs b/benches/example_births_deaths/example_births_deaths.rs index 0efb557d..c8ef12b5 100644 --- a/benches/example_births_deaths/example_births_deaths.rs +++ b/benches/example_births_deaths/example_births_deaths.rs @@ -1,14 +1,11 @@ -use crate::parameters_loader::Parameters; use criterion::{criterion_group, criterion_main, Criterion}; use ixa::{Context, ContextGlobalPropertiesExt, ContextRandomExt}; use std::path::Path; -mod demographics_report; -mod incidence_report; -mod infection_manager; -mod parameters_loader; -mod population_manager; -mod transmission_manager; +use ixa_example_births_deaths::{ + demographics_report, incidence_report, infection_manager, parameters_loader, + population_manager, transmission_manager, +}; fn births_deaths() -> Context { let mut context = Context::new(); @@ -19,7 +16,7 @@ fn births_deaths() -> Context { .expect("failed to load parameters"); let parameters = context - .get_global_property_value(Parameters) + .get_global_property_value(parameters_loader::Parameters) .unwrap() .clone(); context.init_random(parameters.seed); diff --git a/benches/example_births_deaths/incidence_report.rs b/benches/example_births_deaths/incidence_report.rs deleted file mode 120000 index d6bd87ac..00000000 --- a/benches/example_births_deaths/incidence_report.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/incidence_report.rs \ No newline at end of file diff --git a/benches/example_births_deaths/infection_manager.rs b/benches/example_births_deaths/infection_manager.rs deleted file mode 120000 index 078f564d..00000000 --- a/benches/example_births_deaths/infection_manager.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/infection_manager.rs \ No newline at end of file diff --git a/benches/example_births_deaths/input.json b/benches/example_births_deaths/input.json deleted file mode 120000 index 3ab14738..00000000 --- a/benches/example_births_deaths/input.json +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/input.json \ No newline at end of file diff --git a/benches/example_births_deaths/input.json b/benches/example_births_deaths/input.json new file mode 100644 index 00000000..0a8d6743 --- /dev/null +++ b/benches/example_births_deaths/input.json @@ -0,0 +1,15 @@ +{ + "population": 100, + "max_time": 780.0, + "seed": 123, + "birth_rate": 0.1, + "death_rate": 0.1, + "foi_groups": [ + {"group_name": "NewBorn", "foi": 0.2}, + {"group_name": "General", "foi": 0.1}, + {"group_name": "OldAdult", "foi": 0.15} + ], + "infection_duration": 5.0, + "output_file": "incidence", + "demographic_output_file": "people_report.csv" +} diff --git a/benches/example_births_deaths/parameters_loader.rs b/benches/example_births_deaths/parameters_loader.rs deleted file mode 120000 index be904bb4..00000000 --- a/benches/example_births_deaths/parameters_loader.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/parameters_loader.rs \ No newline at end of file diff --git a/benches/example_births_deaths/population_manager.rs b/benches/example_births_deaths/population_manager.rs deleted file mode 120000 index f89545d9..00000000 --- a/benches/example_births_deaths/population_manager.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/population_manager.rs \ No newline at end of file diff --git a/benches/example_births_deaths/transmission_manager.rs b/benches/example_births_deaths/transmission_manager.rs deleted file mode 120000 index 8ee770e9..00000000 --- a/benches/example_births_deaths/transmission_manager.rs +++ /dev/null @@ -1 +0,0 @@ -../../examples/births-deaths/transmission_manager.rs \ No newline at end of file diff --git a/criterion.toml b/criterion.toml index f8b969ef..44e6b1c8 100644 --- a/criterion.toml +++ b/criterion.toml @@ -19,7 +19,7 @@ # This is used to configure the plotting backend used by cargo-criterion. # Options are "gnuplot" and "plotters", or "auto", which will use gnuplot if it's # available or plotters if it isn't. -ploting_backend = "auto" +plotting_backend = "auto" # The colors table allows users to configure the colors used by the charts # cargo-criterion generates. diff --git a/examples/basic-infection/Cargo.toml b/examples/basic-infection/Cargo.toml new file mode 100644 index 00000000..4545fde1 --- /dev/null +++ b/examples/basic-infection/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ixa_example_basic_infection" +version = "0.1.0" +edition = "2021" + +publish = false + +[dependencies] + +ixa = { path = "../../../ixa" } +ixa-derive = { path = "../../ixa-derive" } + +csv = "^1.3.1" +serde = "^1.0.217" +rand = "^0.8.5" +rand_distr = "^0.4.3" +paste = "^1.0.15" + +[[bin]] +name = "basic_infection" +path = "main.rs" diff --git a/examples/basic-infection/main.rs b/examples/basic-infection/main.rs index d50c255a..1b72e846 100644 --- a/examples/basic-infection/main.rs +++ b/examples/basic-infection/main.rs @@ -1,33 +1,4 @@ -use ixa::context::Context; -use ixa::error::IxaError; -use ixa::random::ContextRandomExt; - -mod incidence_report; -mod infection_manager; -mod people; -mod transmission_manager; - -static POPULATION: u64 = 1000; -static SEED: u64 = 123; -static MAX_TIME: f64 = 303.0; -static FOI: f64 = 0.1; -static INFECTION_DURATION: f64 = 5.0; - -fn initialize() -> Result { - let mut context = Context::new(); - - context.init_random(SEED); - - people::init(&mut context); - transmission_manager::init(&mut context); - infection_manager::init(&mut context); - incidence_report::init(&mut context)?; - - context.add_plan(MAX_TIME, |context| { - context.shutdown(); - }); - Ok(context) -} +use ixa_example_basic_infection::initialize; fn main() { let mut context = initialize().expect("Error adding report."); diff --git a/examples/basic-infection/incidence_report.rs b/examples/basic-infection/src/incidence_report.rs similarity index 95% rename from examples/basic-infection/incidence_report.rs rename to examples/basic-infection/src/incidence_report.rs index 7aabbe56..2e5d12f4 100644 --- a/examples/basic-infection/incidence_report.rs +++ b/examples/basic-infection/src/incidence_report.rs @@ -32,7 +32,7 @@ pub fn init(context: &mut Context) -> Result<(), IxaError> { // examples. context .report_options() - .directory(PathBuf::from("./examples/basic-infection/")) + .directory(PathBuf::from("../")) .overwrite(true); context.add_report::("incidence")?; context.subscribe_to_event::(handle_infection_status_change); diff --git a/examples/basic-infection/infection_manager.rs b/examples/basic-infection/src/infection_manager.rs similarity index 100% rename from examples/basic-infection/infection_manager.rs rename to examples/basic-infection/src/infection_manager.rs diff --git a/examples/basic-infection/src/lib.rs b/examples/basic-infection/src/lib.rs new file mode 100644 index 00000000..f4958d46 --- /dev/null +++ b/examples/basic-infection/src/lib.rs @@ -0,0 +1,30 @@ +use ixa::context::Context; +use ixa::error::IxaError; +use ixa::random::ContextRandomExt; + +pub mod incidence_report; +pub mod infection_manager; +pub mod people; +pub mod transmission_manager; + +static POPULATION: u64 = 1000; +static SEED: u64 = 123; +static MAX_TIME: f64 = 303.0; +static FOI: f64 = 0.1; +static INFECTION_DURATION: f64 = 5.0; + +pub fn initialize() -> Result { + let mut context = Context::new(); + + context.init_random(SEED); + + people::init(&mut context); + transmission_manager::init(&mut context); + infection_manager::init(&mut context); + incidence_report::init(&mut context)?; + + context.add_plan(MAX_TIME, |context| { + context.shutdown(); + }); + Ok(context) +} diff --git a/examples/basic-infection/people.rs b/examples/basic-infection/src/people.rs similarity index 100% rename from examples/basic-infection/people.rs rename to examples/basic-infection/src/people.rs diff --git a/examples/basic-infection/transmission_manager.rs b/examples/basic-infection/src/transmission_manager.rs similarity index 100% rename from examples/basic-infection/transmission_manager.rs rename to examples/basic-infection/src/transmission_manager.rs diff --git a/examples/births-deaths/Cargo.toml b/examples/births-deaths/Cargo.toml new file mode 100644 index 00000000..d42eb4f3 --- /dev/null +++ b/examples/births-deaths/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "ixa_example_births_deaths" +version = "0.1.0" +edition = "2021" + +publish = false + +[dependencies] + +ixa = { path = "../../../ixa" } +ixa-derive = { path = "../../ixa-derive" } + +csv = "^1.3.1" +ctor = "^0.2.8" +serde = "^1.0.217" +rand = "^0.8.5" +rand_distr = "^0.4.3" +paste = "^1.0.15" + +[[bin]] +name = "births_deaths" +path = "main.rs" diff --git a/examples/births-deaths/main.rs b/examples/births-deaths/main.rs index 4d9f2ae2..7cdad814 100644 --- a/examples/births-deaths/main.rs +++ b/examples/births-deaths/main.rs @@ -1,46 +1,6 @@ -use ixa::error::IxaError; -use ixa::random::ContextRandomExt; -use ixa::{context::Context, global_properties::ContextGlobalPropertiesExt}; -use std::path::Path; - -mod demographics_report; -mod incidence_report; -mod infection_manager; -mod parameters_loader; -mod population_manager; -mod transmission_manager; - -use crate::parameters_loader::Parameters; - -fn initialize() -> Result { - let mut context = Context::new(); - let current_dir = Path::new(file!()).parent().unwrap(); - let file_path = current_dir.join("input.json"); - - parameters_loader::init_parameters(&mut context, &file_path)?; - - let parameters = context - .get_global_property_value(Parameters) - .unwrap() - .clone(); - context.init_random(parameters.seed); - - demographics_report::init(&mut context)?; - incidence_report::init(&mut context)?; - - population_manager::init(&mut context); - transmission_manager::init(&mut context); - infection_manager::init(&mut context); - - context.add_plan(parameters.max_time, |context| { - context.shutdown(); - }); - println!("{parameters:?}"); - Ok(context) -} +use ixa_example_births_deaths::initialize; fn main() { let mut context = initialize().expect("Could not initialize context."); - context.execute(); } diff --git a/examples/births-deaths/demographics_report.rs b/examples/births-deaths/src/demographics_report.rs similarity index 97% rename from examples/births-deaths/demographics_report.rs rename to examples/births-deaths/src/demographics_report.rs index e4e6e531..65a41f75 100644 --- a/examples/births-deaths/demographics_report.rs +++ b/examples/births-deaths/src/demographics_report.rs @@ -10,7 +10,6 @@ use ixa::{ }; use serde::{Deserialize, Serialize}; use std::path::Path; -use std::path::PathBuf; #[derive(Serialize, Deserialize, Clone)] struct PersonReportItem { @@ -72,9 +71,10 @@ pub fn init(context: &mut Context) -> Result<(), IxaError> { .clone(); let current_dir = Path::new(file!()).parent().unwrap(); + let current_dir = current_dir.join(Path::new("..")); context .report_options() - .directory(PathBuf::from(current_dir)) + .directory(current_dir) .overwrite(true); // Not recommended for production. See `basic-infection/incidence-report`. context.add_report::(¶meters.demographic_output_file)?; diff --git a/examples/births-deaths/incidence_report.rs b/examples/births-deaths/src/incidence_report.rs similarity index 97% rename from examples/births-deaths/incidence_report.rs rename to examples/births-deaths/src/incidence_report.rs index ade163f0..93cf7855 100644 --- a/examples/births-deaths/incidence_report.rs +++ b/examples/births-deaths/src/incidence_report.rs @@ -47,6 +47,7 @@ pub fn init(context: &mut Context) -> Result<(), IxaError> { .unwrap() .clone(); let current_dir = Path::new(file!()).parent().unwrap(); + let current_dir = current_dir.join(Path::new("..")); context .report_options() .directory(PathBuf::from(current_dir)) diff --git a/examples/births-deaths/infection_manager.rs b/examples/births-deaths/src/infection_manager.rs similarity index 100% rename from examples/births-deaths/infection_manager.rs rename to examples/births-deaths/src/infection_manager.rs diff --git a/examples/births-deaths/src/lib.rs b/examples/births-deaths/src/lib.rs new file mode 100644 index 00000000..2f88cff7 --- /dev/null +++ b/examples/births-deaths/src/lib.rs @@ -0,0 +1,40 @@ +use ixa::error::IxaError; +use ixa::random::ContextRandomExt; +use ixa::{context::Context, global_properties::ContextGlobalPropertiesExt}; +use std::path::Path; + +pub mod demographics_report; +pub mod incidence_report; +pub mod infection_manager; +pub mod parameters_loader; +pub mod population_manager; +pub mod transmission_manager; + +use crate::parameters_loader::Parameters; + +pub fn initialize() -> Result { + let mut context = Context::new(); + let current_dir = Path::new(file!()).parent().unwrap(); + let file_path = current_dir.join("../input.json"); + + parameters_loader::init_parameters(&mut context, &file_path)?; + + let parameters = context + .get_global_property_value(Parameters) + .unwrap() + .clone(); + context.init_random(parameters.seed); + + demographics_report::init(&mut context)?; + incidence_report::init(&mut context)?; + + population_manager::init(&mut context); + transmission_manager::init(&mut context); + infection_manager::init(&mut context); + + context.add_plan(parameters.max_time, |context| { + context.shutdown(); + }); + println!("{parameters:?}"); + Ok(context) +} diff --git a/examples/births-deaths/parameters_loader.rs b/examples/births-deaths/src/parameters_loader.rs similarity index 100% rename from examples/births-deaths/parameters_loader.rs rename to examples/births-deaths/src/parameters_loader.rs diff --git a/examples/births-deaths/population_manager.rs b/examples/births-deaths/src/population_manager.rs similarity index 100% rename from examples/births-deaths/population_manager.rs rename to examples/births-deaths/src/population_manager.rs diff --git a/examples/births-deaths/transmission_manager.rs b/examples/births-deaths/src/transmission_manager.rs similarity index 100% rename from examples/births-deaths/transmission_manager.rs rename to examples/births-deaths/src/transmission_manager.rs