diff options
author | Aria <me@aria.rip> | 2023-12-14 21:03:51 +0000 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-12-14 21:03:51 +0000 |
commit | 5545e09290dee3e1b87454741d1070773390dd15 (patch) | |
tree | c15fd6d9c11e16087767e26fa97444a73b67be3d /src | |
parent | 3f89609f2ec1ac3863fb4b7220e0f0fed3ffd039 (diff) |
feat(cli): reimplement cli bits
Diffstat (limited to 'src')
-rw-r--r-- | src/crates/candelabra/src/profiler.rs | 22 | ||||
-rw-r--r-- | src/crates/cli/Cargo.toml | 11 | ||||
-rw-r--r-- | src/crates/cli/src/candidates.rs | 30 | ||||
-rw-r--r-- | src/crates/cli/src/library.rs | 21 | ||||
-rw-r--r-- | src/crates/cli/src/main.rs | 125 | ||||
-rw-r--r-- | src/crates/cli/src/model.rs | 25 | ||||
-rw-r--r-- | src/crates/cli/src/profile.rs | 44 |
7 files changed, 235 insertions, 43 deletions
diff --git a/src/crates/candelabra/src/profiler.rs b/src/crates/candelabra/src/profiler.rs index 46acd66..056e812 100644 --- a/src/crates/candelabra/src/profiler.rs +++ b/src/crates/candelabra/src/profiler.rs @@ -27,21 +27,21 @@ pub(crate) struct CacheEntry { /// The information we get from profiling. #[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct ProfilerInfo(Vec<CollectionLifetime>); +pub struct ProfilerInfo(pub Vec<CollectionLifetime>); /// Profiler info collected from the lifetime of a single collection instance #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CollectionLifetime { - n: usize, - contains: usize, - insert: usize, - clear: usize, - remove: usize, - first: usize, - last: usize, - nth: usize, - push: usize, - pop: usize, + pub n: usize, + pub contains: usize, + pub insert: usize, + pub clear: usize, + pub remove: usize, + pub first: usize, + pub last: usize, + pub nth: usize, + pub push: usize, + pub pop: usize, } impl State { diff --git a/src/crates/cli/Cargo.toml b/src/crates/cli/Cargo.toml index c0180ee..95fb5cc 100644 --- a/src/crates/cli/Cargo.toml +++ b/src/crates/cli/Cargo.toml @@ -1,9 +1,16 @@ [package] -name = "cli" +name = "candelabra-cli" version = "0.1.0" edition = "2021" +default-run = "candelabra-cli" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -candelabra = { path = "../candelabra" }
\ No newline at end of file +candelabra = { path = "../candelabra" } +log = { workspace = true } +anyhow = { workspace = true } +env_logger = { workspace = true } +argh = { version = "0.1.12" } +cargo_metadata = "0.18.1" +tabled = "0.14.0" diff --git a/src/crates/cli/src/candidates.rs b/src/crates/cli/src/candidates.rs new file mode 100644 index 0000000..764f45f --- /dev/null +++ b/src/crates/cli/src/candidates.rs @@ -0,0 +1,30 @@ +use anyhow::Result; +use argh::FromArgs; +use log::info; + +use crate::State; + +/// List selection sites and their candidates +#[derive(FromArgs)] +#[argh(subcommand, name = "candidates")] +pub struct Args {} + +impl State { + pub fn cmd_candidates(&self, _: Args) -> Result<()> { + for proj in self.projects.iter() { + info!("Processing project {}", &proj.name); + + let candidates = self.inner.project_candidate_list(proj)?; + for (file, sites) in candidates { + info!("{}:", file); + for (name, candidates) in sites { + info!(" {}:", name); + for candidate in candidates { + info!(" {}", candidate); + } + } + } + } + Ok(()) + } +} diff --git a/src/crates/cli/src/library.rs b/src/crates/cli/src/library.rs new file mode 100644 index 0000000..7859b0f --- /dev/null +++ b/src/crates/cli/src/library.rs @@ -0,0 +1,21 @@ +use anyhow::Result; +use argh::FromArgs; +use log::info; + +use crate::State; + +/// List all implementations in the library +#[derive(FromArgs)] +#[argh(subcommand, name = "list-library")] +pub struct Args {} + +impl State { + pub fn cmd_library(&self, _: Args) -> Result<()> { + info!("Available container implementations:"); + for name in self.inner.lib_specs().keys() { + info!(" {}", name); + } + + Ok(()) + } +} diff --git a/src/crates/cli/src/main.rs b/src/crates/cli/src/main.rs index 5bd0f34..1633105 100644 --- a/src/crates/cli/src/main.rs +++ b/src/crates/cli/src/main.rs @@ -1,32 +1,97 @@ -fn main() { - println!("Hello, world!"); +use anyhow::{anyhow, Context, Result}; +use argh::FromArgs; +use candelabra::{Paths, Project}; +use log::info; + +mod candidates; +mod library; +mod model; +mod profile; + +#[derive(FromArgs)] +/// Find the best performing container type using primrose +pub struct Args { + /// path to Cargo.toml + #[argh(option)] + pub manifest_path: Option<String>, + + /// project to run on, if in a workspace + #[argh(option, short = 'p')] + pub project: Option<String>, + + #[argh(subcommand)] + pub cmd: Subcommand, } -// fn get_projects(args: &Args) -> Result<Vec<Project>> { -// let mut cmd = cargo_metadata::MetadataCommand::new(); -// if let Some(p) = &args.manifest_path { -// cmd.manifest_path(p); -// } - -// let metadata = cmd.exec().context("failed to get manifest metadata")?; - -// if let Some(p) = &args.project { -// // Select a specific project -// Ok(vec![metadata -// .packages -// .iter() -// .find(|pkg| pkg.name == *p) -// .map(|pkg| Project::new(pkg.clone())) -// .ok_or_else(|| { -// anyhow!("specified project does not exist") -// })?]) -// } else { -// // Default to all workspace members -// Ok(metadata -// .workspace_members -// .iter() -// .flat_map(|member| metadata.packages.iter().find(|pkg| pkg.id == *member)) -// .map(|pkg| Project::new(pkg.clone())) -// .collect()) -// } -// } +#[derive(FromArgs)] +#[argh(subcommand)] +pub enum Subcommand { + Model(model::Args), + Library(library::Args), + Candidates(candidates::Args), + Profile(profile::Args), +} + +fn main() -> Result<()> { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); + let args: Args = argh::from_env(); + + // Build shared state + let paths = Paths::default(); + info!("Using source dir: {:?}", &paths.base); + let state = State { + inner: candelabra::State::new(paths)?, + projects: get_projects(&args)?, + }; + + match args.cmd { + Subcommand::Model(a) => state.cmd_model(a), + Subcommand::Library(a) => state.cmd_library(a), + Subcommand::Candidates(a) => state.cmd_candidates(a), + Subcommand::Profile(a) => state.cmd_profile(a), + } +} + +struct State { + inner: candelabra::State, + projects: Vec<Project>, +} + +// #[derive(FromArgs)] +// /// Show the candidate types selected by primrose +// #[argh(subcommand, name = "candidates")] +// pub struct CandidatesSubcommand {} + +// #[derive(FromArgs)] +// /// Show the profiling information generated from benchmarks +// #[argh(subcommand, name = "profile")] +// pub struct ProfileSubcommand {} + +fn get_projects(args: &Args) -> Result<Vec<Project>> { + let mut cmd = cargo_metadata::MetadataCommand::new(); + if let Some(p) = &args.manifest_path { + cmd.manifest_path(p); + } + + let metadata = cmd.exec().context("failed to get manifest metadata")?; + + if let Some(p) = &args.project { + // Select a specific project + Ok(vec![metadata + .packages + .iter() + .find(|pkg| pkg.name == *p) + .map(|pkg| Project::new(pkg.clone())) + .ok_or_else(|| { + anyhow!("specified project does not exist") + })?]) + } else { + // Default to all workspace members + Ok(metadata + .workspace_members + .iter() + .flat_map(|member| metadata.packages.iter().find(|pkg| pkg.id == *member)) + .map(|pkg| Project::new(pkg.clone())) + .collect()) + } +} diff --git a/src/crates/cli/src/model.rs b/src/crates/cli/src/model.rs new file mode 100644 index 0000000..58f0639 --- /dev/null +++ b/src/crates/cli/src/model.rs @@ -0,0 +1,25 @@ +use anyhow::Result; +use argh::FromArgs; +use log::info; + +use crate::State; + +/// Show the cost model for the given implementation +#[derive(FromArgs)] +#[argh(subcommand, name = "cost-model")] +pub struct Args { + /// the implementation to get the cost model of. + #[argh(positional)] + name: String, +} + +impl State { + pub fn cmd_model(&self, args: Args) -> Result<()> { + info!("Calculating cost model for {}", &args.name); + let model = self.inner.cost_model(&args.name)?; + + dbg!(model); + + Ok(()) + } +} diff --git a/src/crates/cli/src/profile.rs b/src/crates/cli/src/profile.rs new file mode 100644 index 0000000..2f8b21b --- /dev/null +++ b/src/crates/cli/src/profile.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use argh::FromArgs; +use candelabra::profiler::ProfilerInfo; +use log::info; +use tabled::{builder::Builder, settings::Style, Table, Tabled}; + +use crate::State; + +/// Profile the selected projects and print the results +#[derive(FromArgs)] +#[argh(subcommand, name = "profile")] +pub struct Args {} + +impl State { + pub fn cmd_profile(&self, _: Args) -> Result<()> { + for proj in self.projects.iter() { + info!("Processing project {}", &proj.name); + + let info = self.inner.profiler_info(proj)?; + + let mut builder = Builder::default(); + builder.set_header([ + "N (cum.)", "contains", "insert", "clear", "remove", "first", "last", "nth", + "push", "pop", + ]); + for info in info.0.iter() { + builder.push_record([ + info.n.to_string(), + info.contains.to_string(), + info.insert.to_string(), + info.clear.to_string(), + info.remove.to_string(), + info.first.to_string(), + info.last.to_string(), + info.nth.to_string(), + info.push.to_string(), + info.pop.to_string(), + ]); + } + println!("{}", builder.build().with(Style::sharp())); + } + Ok(()) + } +} |