From fb0a6a551405810f502e806b59f396a9b7dda4aa Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 18 Jul 2022 21:12:58 +1000 Subject: [PATCH] Use jobserver to limit parallism of `cargo-install` Since we execute multiple `cargo-install` concurrently, we must use jobserver to limit the parallism so that they won't spawn too much processes/threads to overload the system. Signed-off-by: Jiahao XU --- src/main.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7ed9199b..ae327319 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::{ ffi::OsString, mem::take, path::{Path, PathBuf}, + process, process::{ExitCode, Termination}, sync::Arc, time::{Duration, Instant}, @@ -208,6 +209,9 @@ async fn entry() -> Result<()> { let crate_names = take(&mut opts.crate_names); let opts = Arc::new(opts); + // Create jobserver client + let jobserver_client = create_jobserver_client()?; + // Initialize reqwest client let client = create_reqwest_client(opts.secure, opts.min_tls_version.map(|v| v.into()))?; @@ -289,6 +293,7 @@ async fn entry() -> Result<()> { opts.clone(), temp_dir_path.clone(), target.clone(), + jobserver_client.clone(), )) }) .collect() @@ -300,10 +305,11 @@ async fn entry() -> Result<()> { let opts = opts.clone(); let temp_dir_path = temp_dir_path.clone(); let target = target.clone(); + let jobserver_client = jobserver_client.clone(); tokio::spawn(async move { let resolution = await_task(task).await??; - install(resolution, opts, temp_dir_path, target).await + install(resolution, opts, temp_dir_path, target, jobserver_client).await }) }) .collect() @@ -540,6 +546,7 @@ async fn install( opts: Arc, temp_dir: Arc, target: Arc, + jobserver_client: jobserver::Client, ) -> Result<()> { match resolution { Resolution::Fetch { @@ -557,7 +564,7 @@ async fn install( } Resolution::InstallFromSource { package } => { if !opts.dry_run { - install_from_source(package, target).await + install_from_source(package, target, jobserver_client).await } else { info!( "Dry-run: running `cargo install {} --version {} --target {target}`", @@ -667,12 +674,19 @@ async fn install_from_package( }) } -async fn install_from_source(package: Package, target: Arc) -> Result<()> { +async fn install_from_source( + package: Package, + target: Arc, + jobserver_client: jobserver::Client, +) -> Result<()> { debug!( "Running `cargo install {} --version {} --target {target}`", package.name, package.version ); - let mut child = Command::new("cargo") + let mut command = process::Command::new("cargo"); + jobserver_client.configure(&mut command); + + let mut child = Command::from(command) .arg("install") .arg(package.name) .arg("--version")