Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use scoped threads for parallelism #117

Merged
merged 7 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading