Skip to content

Commit 38ab8dd

Browse files
committed
parallelise walker
1 parent 0f4db59 commit 38ab8dd

File tree

4 files changed

+91
-29
lines changed

4 files changed

+91
-29
lines changed

Cargo.lock

Lines changed: 40 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxvg/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ config = { version = "0.15", features = ["json", "json5"] }
3030
log = { workspace = true }
3131
serde = { workspace = true }
3232
serde_json = { workspace = true }
33-
walkdir = "2.5.0"
33+
ignore = "0.4"

crates/oxvg/src/optimise.rs

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
use std::{
2+
cell::RefCell,
23
ffi::OsStr,
34
io::{IsTerminal, Read, Write},
45
path::PathBuf,
56
str::FromStr,
67
};
78

89
use anyhow::anyhow;
10+
use ignore::{WalkBuilder, WalkState};
911
use oxvg_ast::{
1012
implementations::markup5ever::{Element5Ever, Node5Ever},
1113
visitor::Info,
1214
};
1315
use oxvg_optimiser::Jobs;
14-
use walkdir::WalkDir;
1516

1617
use crate::{args::RunCommand, config::Config};
1718

@@ -29,8 +30,15 @@ pub struct Optimise {
2930
/// If no config is specified the current config will be printed instead.
3031
#[clap(long, short, num_args(0..=1))]
3132
pub config: Option<Vec<PathBuf>>,
33+
/// If the path is a directory, whether to walk through and optimise it's subdirectories
3234
#[clap(long, short, default_value = "false")]
3335
pub recursive: bool,
36+
/// Search through hidden files and directories
37+
#[clap(long, short = '.', default_value = "false")]
38+
pub hidden: bool,
39+
/// Sets the approximate number of threads to use. A value of 0 (default) will automatically determine the appropriate number
40+
#[clap(long, short, default_value = "0")]
41+
pub threads: usize,
3442
}
3543

3644
impl RunCommand for Optimise {
@@ -39,9 +47,11 @@ impl RunCommand for Optimise {
3947
let Some(config) = config else {
4048
return Ok(());
4149
};
42-
let jobs = config.optimise.unwrap_or_default();
50+
if let Some(jobs) = config.optimise {
51+
LOADED_JOBS.set(jobs);
52+
}
4353

44-
self.handle_paths(&jobs)
54+
self.handle_paths()
4555
}
4656
}
4757

@@ -52,7 +62,7 @@ impl Optimise {
5262
dom.serialize_into(wr)
5363
}
5464

55-
fn handle_stdin(&self, jobs: &Jobs<Element5Ever>) -> anyhow::Result<()> {
65+
fn handle_stdin(&self, jobs: Jobs<Element5Ever>) -> anyhow::Result<()> {
5666
use oxvg_ast::parse::Node;
5767

5868
let mut string = String::new();
@@ -63,7 +73,7 @@ impl Optimise {
6373
path: None,
6474
multipass_count: 0,
6575
};
66-
jobs.clone().run(&dom, &info)?;
76+
jobs.run(&dom, &info)?;
6777

6878
if let Some(output) = &self.output.as_ref().and_then(|o| {
6979
eprintln!("Warning: Using empty `-o,--output` with stdin will print to stdout, you can instead omit `-o,--output`.");
@@ -124,7 +134,7 @@ impl Optimise {
124134
}
125135
}
126136

127-
fn handle_path(&self, jobs: &Jobs<Element5Ever>, path: &PathBuf) -> anyhow::Result<()> {
137+
fn handle_path(&self, path: &PathBuf) {
128138
let output_path = |input: &PathBuf| {
129139
let Some(output) = self.output.as_ref() else {
130140
return Ok(None);
@@ -134,34 +144,44 @@ impl Optimise {
134144
};
135145
input.strip_prefix(path).map(|p| Some(output.join(p)))
136146
};
137-
let mut walker = WalkDir::new(path);
138-
if !self.recursive {
139-
walker = walker.max_depth(1);
140-
}
141-
for file in walker.follow_links(true) {
142-
let file = file?;
143-
if !file.file_type().is_file() {
144-
continue;
145-
}
146-
let path = file.into_path();
147-
if path.extension().and_then(OsStr::to_str) != Some("svg") {
148-
continue;
149-
}
150-
Self::handle_file(jobs, &path, output_path(&path)?.as_ref())?;
151-
}
152-
153-
Ok(())
147+
WalkBuilder::new(path)
148+
.max_depth(if self.recursive { None } else { Some(1) })
149+
.follow_links(true)
150+
.threads(self.threads)
151+
.build_parallel()
152+
.run(|| {
153+
Box::new(move |path| {
154+
let jobs = LOADED_JOBS.with_borrow(Clone::clone);
155+
let Ok(path) = path else {
156+
return WalkState::Continue;
157+
};
158+
if !path.file_type().is_some_and(|f| f.is_file()) {
159+
return WalkState::Continue;
160+
}
161+
let path = path.into_path();
162+
if path.extension().and_then(OsStr::to_str) != Some("svg") {
163+
return WalkState::Continue;
164+
}
165+
let Ok(output_path) = output_path(&path) else {
166+
return WalkState::Continue;
167+
};
168+
if let Err(err) = Self::handle_file(&jobs, &path, output_path.as_ref()) {
169+
eprintln!("{err}");
170+
};
171+
WalkState::Continue
172+
})
173+
});
154174
}
155175

156-
fn handle_paths(&self, jobs: &Jobs<Element5Ever>) -> anyhow::Result<()> {
176+
fn handle_paths(&self) -> anyhow::Result<()> {
157177
if !std::io::stdin().is_terminal()
158178
&& self.paths.len() <= 1
159179
&& self
160180
.paths
161181
.first()
162182
.is_none_or(|path| path == &PathBuf::from_str(".").unwrap())
163183
{
164-
return self.handle_stdin(jobs);
184+
return LOADED_JOBS.with(|jobs| self.handle_stdin(jobs.take()));
165185
}
166186
if self.paths.is_empty() {
167187
return Err(anyhow!(
@@ -170,7 +190,7 @@ impl Optimise {
170190
}
171191

172192
for path in &self.paths {
173-
self.handle_path(jobs, path)?;
193+
self.handle_path(path);
174194
}
175195
Ok(())
176196
}
@@ -199,3 +219,7 @@ impl Optimise {
199219
}
200220
}
201221
}
222+
223+
thread_local! {
224+
static LOADED_JOBS: RefCell<Jobs<Element5Ever>> = RefCell::new(Jobs::default());
225+
}

crates/oxvg_optimiser/src/jobs/remove_deprecated_attrs.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ impl RemoveDeprecatedAttrs {
143143
group_deprecated_unsafe: Option<&phf::Set<&'static str>>,
144144
attributes_in_stylesheet: &AttrStylesheet,
145145
) {
146-
dbg!(&group_deprecated_safe, &group_deprecated_unsafe);
147146
if let Some(deprecated) = group_deprecated_safe {
148147
for deprecated in deprecated {
149148
let (prefix, local_name) = match deprecated.split_once(':') {

0 commit comments

Comments
 (0)