Improve Python uninstall perf by removing unnecessary call to installations.find_all() (#14180)

#13954 introduced an unnecessary slow-down to Python uninstall by
calling `installations.find_all()` to discover remaining installations
after an uninstall. Instead, we can filter all initial installations
against those in `uninstalled`.

As part of this change, I've updated `uninstalled` from a `Vec` to an
`IndexSet` in order to do efficient lookups in the filter. This required
a change I call out below to how we were retrieving them for messaging.
This commit is contained in:
John Mumm
2025-06-23 09:51:44 -04:00
committed by GitHub
parent 6481aa3e64
commit b06dec8398
+15 -15
View File
@@ -200,13 +200,13 @@ async fn do_uninstall(
});
}
let mut uninstalled = vec![];
let mut uninstalled = IndexSet::<PythonInstallationKey>::default();
let mut errors = vec![];
while let Some((key, result)) = tasks.next().await {
if let Err(err) = result {
errors.push((key.clone(), anyhow::Error::new(err)));
} else {
uninstalled.push(key.clone());
uninstalled.insert(key.clone());
}
}
@@ -223,14 +223,15 @@ async fn do_uninstall(
// Read all existing managed installations and find the highest installed patch
// for each installed minor version. Ensure the minor version link directory
// is still valid.
let uninstalled_minor_versions = &uninstalled.iter().fold(
IndexSet::<&PythonInstallationMinorVersionKey>::default(),
|mut minor_versions, key| {
minor_versions.insert(PythonInstallationMinorVersionKey::ref_cast(key));
minor_versions
},
);
let remaining_installations: Vec<_> = installations.find_all()?.collect();
let uninstalled_minor_versions: IndexSet<_> = uninstalled
.iter()
.map(PythonInstallationMinorVersionKey::ref_cast)
.collect();
let remaining_installations: Vec<_> = installed_installations
.into_iter()
.filter(|installation| !uninstalled.contains(installation.key()))
.collect();
let remaining_minor_versions =
PythonInstallationMinorVersionKey::highest_installations_by_minor_version_key(
remaining_installations.iter(),
@@ -278,28 +279,27 @@ async fn do_uninstall(
}
// Report on any uninstalled installations.
if !uninstalled.is_empty() {
if let [uninstalled] = uninstalled.as_slice() {
if let Some(first_uninstalled) = uninstalled.first() {
if uninstalled.len() == 1 {
// Ex) "Uninstalled Python 3.9.7 in 1.68s"
writeln!(
printer.stderr(),
"{}",
format!(
"Uninstalled {} {}",
format!("Python {}", uninstalled.version()).bold(),
format!("Python {}", first_uninstalled.version()).bold(),
format!("in {}", elapsed(start.elapsed())).dimmed()
)
.dimmed()
)?;
} else {
// Ex) "Uninstalled 2 versions in 1.68s"
let s = if uninstalled.len() == 1 { "" } else { "s" };
writeln!(
printer.stderr(),
"{}",
format!(
"Uninstalled {} {}",
format!("{} version{s}", uninstalled.len()).bold(),
format!("{} versions", uninstalled.len()).bold(),
format!("in {}", elapsed(start.elapsed())).dimmed()
)
.dimmed()