Skip to content

Commit f5cea1a

Browse files
committed
Set a maximum thread limit for remove_dir_all
Under the hood it uses rayon so we pre-initialize the global pool.
1 parent 7888e25 commit f5cea1a

File tree

5 files changed

+20
-8
lines changed

5 files changed

+20
-8
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ opentelemetry_sdk = { version = "0.30", features = ["rt-tokio"], optional = true
6969
platforms = "3.4"
7070
pulldown-cmark = { version = "0.13", default-features = false }
7171
rand = "0.9"
72+
rayon = "1.10.0"
7273
regex = "1"
7374
remove_dir_all = { version = "1.0.0", features = ["parallel"] }
7475
reqwest = { version = "0.12", default-features = false, features = ["blocking", "gzip", "http2", "socks", "stream"], optional = true }

src/diskio/mod.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ use std::io::{self, Write};
6060
use std::ops::{Deref, DerefMut};
6161
use std::path::{Path, PathBuf};
6262
use std::sync::mpsc::Receiver;
63-
use std::thread::available_parallelism;
6463
use std::time::{Duration, Instant};
6564
use std::{fmt::Debug, fs::OpenOptions};
6665

6766
use anyhow::{Context, Result};
6867

6968
use crate::process::Process;
69+
use crate::utils;
7070
use crate::utils::notifications::Notification;
7171
use threaded::PoolReference;
7272

@@ -448,15 +448,9 @@ pub(crate) fn get_executor<'a>(
448448
ram_budget: usize,
449449
process: &Process,
450450
) -> Result<Box<dyn Executor + 'a>> {
451-
// Don't spawn more than this many I/O threads unless the user tells us to.
452-
const DEFAULT_THREAD_LIMIT: usize = 8;
453-
454451
// If this gets lots of use, consider exposing via the config file.
455452
let thread_count = match process.var("RUSTUP_IO_THREADS") {
456-
Err(_) => available_parallelism()
457-
.map(|p| p.get())
458-
.unwrap_or(1)
459-
.min(DEFAULT_THREAD_LIMIT),
453+
Err(_) => utils::io_thread_count(),
460454
Ok(n) => n
461455
.parse::<usize>()
462456
.context("invalid value in RUSTUP_IO_THREADS. Must be a natural number")?,

src/install.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ impl InstallMethod<'_> {
3939
// Install a toolchain
4040
#[tracing::instrument(level = "trace", err(level = "trace"), skip_all)]
4141
pub(crate) async fn install(&self) -> Result<UpdateStatus> {
42+
// Initialize rayon for use by the remove_dir_all crate limiting the number of threads.
43+
// This will error if rayon is already initialized but it's fine to ignore that.
44+
let _ = rayon::ThreadPoolBuilder::new()
45+
.num_threads(utils::io_thread_count())
46+
.build_global();
4247
let nh = &self.cfg().notify_handler;
4348
match self {
4449
InstallMethod::Copy { .. }

src/utils/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::io::{self, BufReader, Write};
77
use std::ops::{BitAnd, BitAndAssign};
88
use std::path::{Path, PathBuf};
99
use std::process::ExitStatus;
10+
use std::thread;
1011

1112
use anyhow::{Context, Result, anyhow, bail};
1213
use retry::delay::{Fibonacci, jitter};
@@ -26,6 +27,16 @@ pub(crate) mod notify;
2627
pub mod raw;
2728
pub(crate) mod units;
2829

30+
pub fn io_thread_count() -> usize {
31+
// Don't spawn more than this many I/O threads unless the user tells us to.
32+
// Feel free to increase this value if it improves performance.
33+
const DEFAULT_IO_THREAD_LIMIT: usize = 8;
34+
35+
thread::available_parallelism()
36+
.map_or(1, |p| p.get())
37+
.min(DEFAULT_IO_THREAD_LIMIT)
38+
}
39+
2940
#[must_use]
3041
#[derive(Debug, PartialEq, Eq)]
3142
pub struct ExitCode(pub i32);

0 commit comments

Comments
 (0)