From 7368adc761f30e92527b21ab60168f223ee2604f Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 11 Aug 2020 19:02:51 +0100 Subject: [PATCH] added max cpu mode --- Cargo.lock | 3 +- Cargo.toml | 3 +- src/arg.rs | 79 ++++++++++++++++++++++++++++++++++++------------- src/main.rs | 22 +++++++++++++- src/progress.rs | 3 -- src/work.rs | 9 +++--- 6 files changed, 87 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7864ff4..9b622e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -188,11 +188,12 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "leanify-many" -version = "0.1.0" +version = "0.2.0" dependencies = [ "cfg-if", "futures", "lazy_static", + "num_cpus", "recolored", "rustc_version", "termprogress", diff --git a/Cargo.toml b/Cargo.toml index ed6f203..e0a237e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leanify-many" -version = "0.1.0" +version = "0.2.0" description = "spawn leanify subprocesses" authors = ["Avril "] edition = "2018" @@ -22,6 +22,7 @@ futures = "0.3" termprogress = {version="0.3", optional=true} cfg-if = "0.1.10" recolored = { version = "1.9.3", optional = true } +num_cpus = "1.13.0" [build-dependencies] rustc_version = "0.2" diff --git a/src/arg.rs b/src/arg.rs index e3161ae..1651ecb 100644 --- a/src/arg.rs +++ b/src/arg.rs @@ -8,6 +8,7 @@ use std::{ PathBuf, Path, }, + marker::PhantomData, }; use lazy_static::lazy_static; @@ -24,9 +25,13 @@ fn extra_args() -> &'static str lazy_static! { static ref EXTRA: &'static str = { let work = || -> Result { + #[allow(unused_imports)] use std::fmt::Write as _; + #[allow(unused_mut)] let mut output = String::new(); #[cfg(feature="progress")] writeln!(output, " --no-progress Do not display progress bar")?; + #[cfg(feature="colour")] writeln!(output, " --no-colour Do not display terminal colours")?; + #[cfg(feature="colour")] writeln!(output, " --colour Always display terminal colour, even if env flags tell us not to")?; Ok(output) }; match work() { @@ -41,54 +46,55 @@ fn extra_args() -> &'static str &EXTRA[..] } +#[allow(unused_variables)] mod feature { use cfg_if::cfg_if; #[macro_export] macro_rules! check { - (on $name:literal) => { + (on $name:literal, $desc:expr) => { if cfg!(feature = $name) { - feature::on($name, true); + feature::on($name, true, $desc); } else { - feature::off($name, false); + feature::off($name, false, $desc); } }; - (off $name:literal) => { + (off $name:literal, $desc:expr) => { if cfg!(feature = $name) { - feature::on($name, false); + feature::on($name, false, $desc); } else { - feature::off($name, true); + feature::off($name, true, $desc); } } } - pub fn on(name: impl AsRef, default: bool) + pub fn on(name: impl AsRef, default: bool, desc: impl AsRef) { cfg_if! { if #[cfg(feature="colour")] { use recolored::Colorize; if default { - println!(" {}", format!("+{}", name.as_ref()).red()); + println!(" {} {}", format!("+{}", name.as_ref()).red(), desc.as_ref().bright_black()); } else { - println!(" {}", format!("+{}", name.as_ref()).bright_red()); + println!(" {} {}", format!("+{}", name.as_ref()).bright_red(), desc.as_ref()); } } else { - println!(" +{}", name.as_ref()) + println!(" +{} {}", name.as_ref(), desc.as_ref()) } } } - pub fn off(name: impl AsRef, default: bool) + pub fn off(name: impl AsRef, default: bool, desc: impl AsRef) { cfg_if! { if #[cfg(feature="colour")] { use recolored::Colorize; if default { - println!(" {}", format!("-{}", name.as_ref()).blue()); + println!(" {} {}", format!("-{}", name.as_ref()).blue(), desc.as_ref().bright_black()); } else { - println!(" {}", format!("-{}", name.as_ref()).bright_blue()); + println!(" {} {}", format!("-{}", name.as_ref()).bright_blue(), desc.as_ref()); } } else { - println!(" -{}", name.as_ref()) + println!(" -{} {}", name.as_ref(), desc.as_ref()) } } } @@ -96,10 +102,10 @@ mod feature fn comp_flags() { - check!(on "splash"); - check!(on "colour"); - check!(on "progress"); - check!(off "threads"); + check!(on "splash", "Show splash-screen"); + check!(on "colour", "Enable coloured output"); + check!(on "progress", "Enable progress bar"); + check!(off "threads", "Enable threaded scheduler (usually not needed)."); } pub fn usage() -> ! @@ -111,15 +117,15 @@ pub fn usage() -> ! Usage: {prog} --help OPTIONS: + - Stop parsing args here. --max-children Max subprocesses allowed to live at once. Infinite by default. + -m Limit subprocesses to number of CPU cores. --recursive Recurse up to `` times. Must be at least `1`. Default is off. -r Resurse infinitely. {extra} - - Stop parsing args here. - ENVIRONMENT VARS: LEANIFY= Path to leanify executable, defaults to looking in `PATH' if set. -", prog = program_name(), extra = &extra_args()[..extra_args().len()-1]); +", prog = program_name(), extra = extra_args()); println!("Compiled with:"); comp_flags(); @@ -132,6 +138,8 @@ pub enum Error { #[cfg(not(nightly))] BadNumber(()), NoExist(PathBuf), Walking(dir::Error), + + Other(&'static str), NoFiles, } impl std::error::Error for Error{} @@ -158,6 +166,7 @@ impl std::fmt::Display for Error Self::NoExist(path) => write!(f, "path {:?} does not exist", path), Self::NoFiles => write!(f, "need at least one argument"), Self::Walking(dir) => write!(f, "error walking directory structure(s): {}", dir), + Self::Other(msg) => write!(f, "{}", msg), } } } @@ -178,6 +187,13 @@ pub struct Flags { /// Display the progress bar #[cfg(feature="progress")] pub progress: bool, + /// Force use of colour + #[cfg(feature="colour")] pub coloured: Option, + /// Limit max children to this number + pub hard_limit: Option, + + /// To shut the linter up when we have no elements here + _data: PhantomData<()>, } impl Default for Flags @@ -187,6 +203,10 @@ impl Default for Flags { Self { #[cfg(feature="progress")] progress: true, + #[cfg(feature="colour")] coloured: None, + hard_limit: None, + + _data: PhantomData, } } } @@ -254,6 +274,13 @@ where I: IntoIterator, continue; } }, + "-m" => { + cfg.flags.hard_limit = NonZeroUsize::new(num_cpus::get()); + if cfg.flags.hard_limit.is_none() { + return Err(Error::Other("-m: Could not determine number of CPUs, try setting max children manually with `--max-children`")); + } + continue; + }, "--recursive" => { if let Some(nzi) = args.next() { cfg.recursive = Some(nzi.parse()?); @@ -265,6 +292,16 @@ where I: IntoIterator, cfg.flags.progress = false; continue; }, + #[cfg(feature="colour")] + "--no-colour" => { + cfg.flags.coloured = Some(false); + continue; + }, + #[cfg(feature="colour")] + "--colour" => { + cfg.flags.coloured = Some(true); + continue; + }, "-r" => { cfg.recursive = None; }, diff --git a/src/main.rs b/src/main.rs index fe9377a..ec77f11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,27 @@ async fn work() -> Result<(), Box> let args = arg::parse_args().await.with_prefix("failed to parse args")?; let leanify = leanify::find_binary().with_prefix("Couldn't find leanify binary")?; - work::work(&args.flags, leanify, args.files, args.max_children).await + #[cfg(feature="colour")] { + match args.flags.coloured { + Some(x) => recolored::control::set_override(x), + _ => {}, + } + } + + work::work(&args.flags, leanify, args.files, match args.flags.hard_limit { + Some(hard_limit) => { + // We have hard limit + match args.max_children { + // We also have max children, and it's higher than hard limit, + Some(max_children) if max_children > hard_limit => Some(hard_limit), + // We have no max children + None => Some(hard_limit), + //Max children is lower than hard limit + _ => args.max_children, + } + }, + _ => args.max_children, + }).await } diff --git a/src/progress.rs b/src/progress.rs index 416e696..582a119 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -1,10 +1,8 @@ use super::*; use std::{ iter::FromIterator as _, - sync::Arc, borrow::{ Cow, - Borrow as _, }, marker::{ Send, @@ -37,7 +35,6 @@ use futures::{ }, }; use termprogress::{ - Display as _, WithTitle, ProgressBar, }; diff --git a/src/work.rs b/src/work.rs index 984de24..ee0ac21 100644 --- a/src/work.rs +++ b/src/work.rs @@ -8,17 +8,16 @@ use std::{ }, path::{Path,PathBuf,}, ffi::OsStr, - borrow::BorrowMut, - iter, }; +#[allow(unused_imports)] +use std::iter; use tokio::{ - prelude::*, sync::{ Semaphore, mpsc, }, - io, }; +#[allow(unused_imports)] use futures::future::{ self, join_all, @@ -83,7 +82,7 @@ async fn do_work(process: impl AsRef, file: impl AsRef, mut prog: P } } -pub async fn work(flags: &arg::Flags, process: U, files: I, children: Option) -> Result<(), Box> +pub async fn work(#[allow(unused_variables)] flags: &arg::Flags, process: U, files: I, children: Option) -> Result<(), Box> where I: IntoIterator, ::IntoIter: ExactSizeIterator, T: AsRef + Send + Sync + 'static + Clone,