Skip to content
Closed
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
36 changes: 26 additions & 10 deletions crates/pm/src/service/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use crate::util::downloader::download_stats;
use crate::util::json::load_package_lock_json_from_path;
use crate::util::linker::link;
use crate::util::logger::{
PROGRESS_BAR, finish_progress_bar, log_progress, print_install_counts, start_progress_bar,
finish_progress_bar, log_progress, print_install_counts, progress_inc, progress_set_length,
start_progress_bar,
};
use utoo_ruborist::compat::{is_cpu_compatible, is_os_compatible};

Expand Down Expand Up @@ -87,9 +88,24 @@ pub async fn install_packages(

if let Some(packages) = groups.get(depth) {
for (path, package) in packages.iter() {
// Cooperative scheduling hint: tells the runtime "I did
// a tick of work" and yields when the per-task budget
// (default 128) exhausts. Before #2903's TTY-gate the
// implicit yield came from indicatif's mutex acquire on
// every progress_inc call; on non-TTY (CI, piped output)
// that's now a no-op and the synchronous loop body runs
// ~2000 packages back-to-back without giving the runtime
// a window to drain socket reads on in-flight tarball
// downloads. Pcap measured `tcp.analysis.zero_window`
// events climb 0 → 14-16 without this hint; with it,
// back to 0. Cost is ~5ns when budget isn't exhausted
// (the common case — JoinHandle.await downstream resets
// budget naturally).
tokio::task::consume_budget().await;

// Skip packages based on omit config
if should_omit_package(package, omit) {
PROGRESS_BAR.inc(1);
progress_inc(1);
continue;
}
let path = path.clone();
Expand All @@ -108,28 +124,28 @@ pub async fn install_packages(
if package.link.is_some() {
let link_name = extract_package_name(&path);
if link_name.is_empty() {
PROGRESS_BAR.inc(1);
progress_inc(1);
continue;
}
link(Path::new(&resolved), Path::new(&path))
.await
.with_context(|| format!("Link failed: {resolved} -> {path}"))?;
PROGRESS_BAR.inc(1);
progress_inc(1);
continue;
}

// skip when cpu or os is not compatible
if let Some(ref cpu) = package.cpu
&& !is_cpu_compatible(cpu)
{
PROGRESS_BAR.inc(1);
progress_inc(1);
continue;
}

if let Some(ref os) = package.os
&& !is_os_compatible(os)
{
PROGRESS_BAR.inc(1);
progress_inc(1);
continue;
}

Expand All @@ -153,18 +169,18 @@ pub async fn install_packages(
tracing::warn!(
"Optional dependency {name} failed (ignored): {e:#}"
);
PROGRESS_BAR.inc(1);
progress_inc(1);
return Ok(());
}
return Err(e);
}
PROGRESS_BAR.inc(1);
progress_inc(1);
log_progress(&format!("{name} resolved"));
update_package_binary(&target_path, &name).await
});
clone_tasks.push(task);
} else {
PROGRESS_BAR.inc(1);
progress_inc(1);
}
}
}
Expand Down Expand Up @@ -260,7 +276,7 @@ impl InstallService {

if !package_lock.packages.is_empty() {
start_progress_bar();
PROGRESS_BAR.set_length(package_lock.packages.len() as u64);
progress_set_length(package_lock.packages.len() as u64);
}

let link_start = Instant::now();
Expand Down
21 changes: 21 additions & 0 deletions crates/pm/src/util/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,27 @@ pub fn log_progress(text: &str) {
PROGRESS_BAR.set_message(text.to_string());
}

/// TTY-gated `PROGRESS_BAR.inc(1)`. Non-TTY callers pay no Mutex cost —
Comment thread
elrrrrrrr marked this conversation as resolved.
Resolved
/// indicatif's `inc` always takes the internal `Mutex<ProgressState>`
/// write-lock even with a hidden draw target, which contends across the
/// install loop's spawned tasks.
#[inline]
pub fn progress_inc(n: u64) {
if !*IS_TTY {
return;
}
PROGRESS_BAR.inc(n);
}

/// TTY-gated `PROGRESS_BAR.set_length`. Same rationale as [`progress_inc`].
#[inline]
pub fn progress_set_length(len: u64) {
if !*IS_TTY {
return;
}
PROGRESS_BAR.set_length(len);
}

// Global timer for log_time/log_time_end
static START_TIME: OnceCell<Instant> = OnceCell::new();

Expand Down
Loading