Skip to content

Commit

Permalink
Use scoped threads for parallelism (#117)
Browse files Browse the repository at this point in the history
* Allow `RustyWind` to be cloned

* Use a scoped_thread instead of actors

* Add debug log to show how many files its checking
  • Loading branch information
praveenperera authored Feb 3, 2025
1 parent 3af70d9 commit d2057ce
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 9 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions rustywind-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ ignore = "0.4"
# parsing
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

# parallelism
num_cpus = "1.16"
41 changes: 41 additions & 0 deletions rustywind-cli/src/heard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/// Heard is a struct that handles running the rustywind on a list of files
/// in parallel. It uses the num_cpus crate to determine the number of
/// physical cores on the machine. It then spawns a thread for each core
/// and runs the rustywind on the file paths.
use crate::options::Options;
use std::{path::PathBuf, sync::Arc};

#[derive(Debug)]
pub struct Heard {
cpus: usize,
options: Arc<Options>,
}

impl Heard {
pub fn new(options: Arc<Options>) -> Self {
let cpus = num_cpus::get_physical();
Self { cpus, options }
}

pub fn run_on_file_paths(self, file_paths: Vec<PathBuf>) {
log::debug!("checking {} files", file_paths.len());

let total_chunks = self.cpus;
let chunks_of = file_paths.len() / total_chunks;
let options = &self.options;

std::thread::scope(|s| {
file_paths.chunks(chunks_of).for_each(|chunk| {
s.spawn(|| {
run_on_file_paths(chunk, options);
});
});
})
}
}

fn run_on_file_paths(file_paths: &[PathBuf], options: &Options) {
for file_path in file_paths {
crate::run_on_file_path(file_path, options);
}
}
19 changes: 13 additions & 6 deletions rustywind-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod cli;
mod heard;
mod options;

use ahash::AHashSet as HashSet;
use clap::Parser;
use eyre::Result;
use heard::Heard;
use indoc::indoc;
use once_cell::sync::Lazy;
use options::Options;
Expand All @@ -14,6 +16,7 @@ use std::path::Path;
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::sync::Arc;

static EXIT_ERROR: Lazy<AtomicBool> = Lazy::new(|| AtomicBool::new(false));
static GRAY: Lazy<colored::CustomColor> = Lazy::new(|| colored::CustomColor::new(120, 120, 120));
Expand Down Expand Up @@ -99,7 +102,12 @@ fn main() -> Result<()> {
color_eyre::install()?;

let cli = Cli::parse();
let options = Options::new_from_cli(cli)?;

let mut options = Options::new_from_cli(cli)?;

let search_paths = std::mem::take(&mut options.search_paths);

let options = Arc::new(options);
let rustywind = &options.rustywind;

match &options.write_mode {
Expand Down Expand Up @@ -132,9 +140,8 @@ fn main() -> Result<()> {
eprint!("[WARN] No classes were found in STDIN");
}
} else {
for file_path in options.search_paths.iter() {
run_on_file_paths(file_path, &options)
}
let heard = Heard::new(options.clone());
heard.run_on_file_paths(search_paths);

// after running on all files, if there was an error, exit with 1
if EXIT_ERROR.load(Ordering::Relaxed) {
Expand All @@ -145,7 +152,7 @@ fn main() -> Result<()> {
Ok(())
}

fn run_on_file_paths(file_path: &Path, options: &Options) {
pub fn run_on_file_path(file_path: &Path, options: &Options) {
// if the file is in the ignored_files list return early
if should_ignore_current_file(&options.ignored_files, file_path) {
log::debug!("file path {file_path:#?} found in ignored_files, will not sort");
Expand Down Expand Up @@ -175,7 +182,7 @@ fn run_on_file_paths(file_path: &Path, options: &Options) {
(true, WriteMode::ToConsole) => print_file_contents(&sorted_content),
(false, WriteMode::ToConsole) => print_file_contents(&sorted_content),

(_, WriteMode::CheckFormatted) => {
(contents_changed, WriteMode::CheckFormatted) => {
print_changed_files(file_path, contents_changed, options);
}
}
Expand Down
2 changes: 1 addition & 1 deletion rustywind-core/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use aho_corasick::{Anchored, Input};
use regex::Captures;

/// The options to pass to the sorter.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct RustyWind {
pub regex: FinderRegex,
pub sorter: Sorter,
Expand Down
4 changes: 2 additions & 2 deletions rustywind-core/src/sorter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) static SORTER_EXTRACTOR_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^(\.[^\s]+)[ ]").unwrap());

/// Use either our default regex in [crate::defaults::RE] or a custom regex.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum FinderRegex {
DefaultRegex,
CustomRegex(Regex),
Expand All @@ -34,7 +34,7 @@ impl Deref for FinderRegex {
}

/// Use either our default sorter in [crate::defaults::SORTER] or a custom sorter.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Sorter {
DefaultSorter,
CustomSorter(HashMap<String, usize>),
Expand Down

0 comments on commit d2057ce

Please sign in to comment.