Skip to content

Commit c7566e4

Browse files
committed
feat!: add support for explicit non-parallel iteration.
That way we can allow the implementation to choose whether they need greatest speed at some cost or not. This also allows us to create a new thread-pool on each iteration as those who expect high cost or many files will likely chose to do that instead of single-threaded iteration, which nicely contains the threads needed and avoids keeping them alive as part of some global pool.
1 parent 42f989a commit c7566e4

File tree

4 files changed

+55
-32
lines changed

4 files changed

+55
-32
lines changed

Cargo.lock

+4-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ check: ## Build all code in suitable configurations
9595
&& cargo check
9696
cd git-features && cargo check --all-features \
9797
&& cargo check --features parallel \
98-
&& cargo check --features parallel,fs-walkdir-parallel \
98+
&& cargo check --features fs-walkdir-parallel \
9999
&& cargo check --features rustsha1 \
100100
&& cargo check --features fast-sha1 \
101101
&& cargo check --features progress \

git-features/Cargo.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ default = []
1919
progress = ["prodash"]
2020

2121
## If set, walkdir iterators will be multi-threaded.
22-
## This feature has [certain side-effects](https://github.com/starship/starship/issues/4251) of rayon threadpool configuration with `jwalk`.
23-
fs-walkdir-parallel = ["parallel", "jwalk" ]
22+
fs-walkdir-parallel = [ "num_cpus", "jwalk" ]
2423

2524
## Use scoped threads and channels to parallelize common workloads on multiple objects. If enabled, it is used everywhere
2625
## where it makes sense.
@@ -107,7 +106,7 @@ crossbeam-channel = { version = "0.5.0", optional = true }
107106
num_cpus = { version = "1.13.0", optional = true }
108107
parking_lot = { version = "0.12.0", default-features = false, optional = true }
109108

110-
jwalk = { version = "0.6.0", optional = true }
109+
jwalk = { version = "0.8.1", optional = true }
111110
## Makes facilities of the `walkdir` crate partially available.
112111
## In conjunction with the **parallel** feature, directory walking will be parallel instead behind a compatible interface.
113112
walkdir = { version = "2.3.2", optional = true } # used when parallel is off

git-features/src/fs.rs

+48-14
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,62 @@
66
//! For information on how to use the [`WalkDir`] type, have a look at
77
//! * [`jwalk::WalkDir`](https://docs.rs/jwalk/0.5.1/jwalk/type.WalkDir.html) if `parallel` feature is enabled
88
//! * [walkdir::WalkDir](https://docs.rs/walkdir/2.3.1/walkdir/struct.WalkDir.html) otherwise
9-
#[cfg(feature = "fs-walkdir-parallel")]
9+
10+
#[cfg(any(feature = "walkdir", feature = "fs-walkdir-parallel"))]
11+
mod shared {
12+
/// The desired level of parallelism.
13+
pub enum Parallelism {
14+
/// Do not parallelize at all by making a serial traversal on the current thread.
15+
Serial,
16+
/// Create a new thread pool for each traversal with up to 16 threads or the amount of logical cores of the machine.
17+
ThreadPoolPerTraversal {
18+
/// The base name of the threads we create as part of the thread-pool.
19+
thread_name: &'static str,
20+
},
21+
}
22+
}
23+
1024
///
25+
#[cfg(feature = "fs-walkdir-parallel")]
1126
pub mod walkdir {
12-
use std::path::Path;
13-
27+
pub use super::shared::Parallelism;
1428
pub use jwalk::{DirEntry as DirEntryGeneric, DirEntryIter as DirEntryIterGeneric, Error, WalkDir};
29+
use std::path::Path;
1530

1631
/// An alias for an uncustomized directory entry to match the one of the non-parallel version offered by `walkdir`.
1732
pub type DirEntry = DirEntryGeneric<((), ())>;
1833

19-
/// Instantiate a new directory iterator which will not skip hidden files.
20-
pub fn walkdir_new(root: impl AsRef<Path>) -> WalkDir {
21-
WalkDir::new(root)
22-
.skip_hidden(false)
23-
.parallelism(jwalk::Parallelism::Serial)
34+
impl From<Parallelism> for jwalk::Parallelism {
35+
fn from(v: Parallelism) -> Self {
36+
match v {
37+
Parallelism::Serial => jwalk::Parallelism::Serial,
38+
Parallelism::ThreadPoolPerTraversal { thread_name } => {
39+
let pool = jwalk::rayon::ThreadPoolBuilder::new()
40+
.num_threads(num_cpus::get().min(16))
41+
.stack_size(128 * 1024)
42+
.thread_name(move |idx| format!("{thread_name} {idx}"))
43+
.build()
44+
.expect("we only set options that can't cause a build failure");
45+
jwalk::Parallelism::RayonExistingPool {
46+
pool: pool.into(),
47+
busy_timeout: None,
48+
}
49+
}
50+
}
51+
}
52+
}
53+
54+
/// Instantiate a new directory iterator which will not skip hidden files, with the given level of `parallelism`.
55+
pub fn walkdir_new(root: impl AsRef<Path>, parallelism: Parallelism) -> WalkDir {
56+
WalkDir::new(root).skip_hidden(false).parallelism(parallelism.into())
2457
}
2558

2659
/// Instantiate a new directory iterator which will not skip hidden files and is sorted
27-
pub fn walkdir_sorted_new(root: impl AsRef<Path>) -> WalkDir {
60+
pub fn walkdir_sorted_new(root: impl AsRef<Path>, parallelism: Parallelism) -> WalkDir {
2861
WalkDir::new(root)
2962
.skip_hidden(false)
3063
.sort(true)
31-
.parallelism(jwalk::Parallelism::Serial)
64+
.parallelism(parallelism.into())
3265
}
3366

3467
/// The Iterator yielding directory items
@@ -38,17 +71,18 @@ pub mod walkdir {
3871
#[cfg(all(feature = "walkdir", not(feature = "fs-walkdir-parallel")))]
3972
///
4073
pub mod walkdir {
74+
pub use super::shared::Parallelism;
4175
use std::path::Path;
4276

4377
pub use walkdir::{DirEntry, Error, WalkDir};
4478

45-
/// Instantiate a new directory iterator which will not skip hidden files.
46-
pub fn walkdir_new(root: impl AsRef<Path>) -> WalkDir {
79+
/// Instantiate a new directory iterator which will not skip hidden files, with the given level of `parallelism`.
80+
pub fn walkdir_new(root: impl AsRef<Path>, _: Parallelism) -> WalkDir {
4781
WalkDir::new(root)
4882
}
4983

50-
/// Instantiate a new directory iterator which will not skip hidden files and is sorted
51-
pub fn walkdir_sorted_new(root: impl AsRef<Path>) -> WalkDir {
84+
/// Instantiate a new directory iterator which will not skip hidden files and is sorted, with the given level of `parallelism`.
85+
pub fn walkdir_sorted_new(root: impl AsRef<Path>, _: Parallelism) -> WalkDir {
5286
WalkDir::new(root).sort_by_file_name()
5387
}
5488

0 commit comments

Comments
 (0)