From 1120e5140bc30270dada47cc864ee56e18e24bda Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Mon, 2 Dec 2024 10:18:40 +0100 Subject: [PATCH] try to speed up `pixi global list` --- Cargo.toml | 3 +++ src/global/common.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/global/list.rs | 39 ++++++++++++++++++++++----------------- src/prefix.rs | 2 +- 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32117ffd0..46ba1d362 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -325,6 +325,7 @@ inherits = "release" lto = "fat" opt-level = 3 strip = "symbols" +debug = false [profile.ci] codegen-units = 16 @@ -333,6 +334,8 @@ lto = false opt-level = 3 strip = false +[profile.release] +debug = true [dev-dependencies] async-trait = { workspace = true } diff --git a/src/global/common.rs b/src/global/common.rs index d04d08fc2..de6ab5557 100644 --- a/src/global/common.rs +++ b/src/global/common.rs @@ -180,6 +180,7 @@ pub(crate) fn is_binary(file_path: impl AsRef) -> miette::Result { /// Finds the package record from the `conda-meta` directory. pub(crate) async fn find_package_records(conda_meta: &Path) -> miette::Result> { + tracing::warn!("Loading package records from {}", conda_meta.display()); let mut read_dir = tokio_fs::read_dir(conda_meta).await.into_diagnostic()?; let mut records = Vec::new(); @@ -202,6 +203,43 @@ pub(crate) async fn find_package_records(conda_meta: &Path) -> miette::Result Result, std::io::Error> { + let mut read_dir = fs::read_dir(conda_meta)?; + let mut records = Vec::new(); + + while let Some(entry) = read_dir.next() { + let entry = entry?; + // Check if the entry is a file and has a .json extension + if matches!(entry.file_type(), Ok(file_type) if file_type.is_file()) { + let file_name = entry.file_name(); + + if let Some(without_ext) = file_name.to_str().and_then(|s| s.strip_suffix(".json")) { + if let Some((build_string, version, name)) = + without_ext.rsplitn(3, '-').next_tuple() + { + records.push(PackageIdentifier { + name: PackageName::from_str(name).unwrap(), + version: Version::from_str(version).unwrap(), + build_string: build_string.to_owned(), + }); + } + } + } + } + + Ok(records) +} + #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum NotChangedReason { AlreadyInstalled, diff --git a/src/global/list.rs b/src/global/list.rs index 93aef3595..65d8a6dec 100644 --- a/src/global/list.rs +++ b/src/global/list.rs @@ -6,7 +6,7 @@ use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; use pixi_consts::consts; use pixi_spec::PixiSpec; -use rattler_conda_types::{PackageName, PackageRecord, PrefixRecord, Version}; +use rattler_conda_types::{PackageName, PackageRecord, Version}; use serde::Serialize; use std::io::Write; @@ -14,7 +14,11 @@ use miette::{miette, IntoDiagnostic}; use crate::global::common::find_package_records; -use super::{project::ParsedEnvironment, EnvChanges, EnvState, EnvironmentName, Mapping, Project}; +use super::{ + common::{find_linked_packages, PackageIdentifier}, + project::ParsedEnvironment, + EnvChanges, EnvState, EnvironmentName, Mapping, Project, +}; /// Sorting strategy for the package table #[derive(clap::ValueEnum, Clone, Debug, Serialize, Default)] @@ -147,7 +151,10 @@ pub async fn list_environment( .environments() .get(environment_name) .ok_or_else(|| miette!("Environment {} not found", environment_name.fancy_display()))?; - + println!( + "Listing packages in the {} environment", + environment_name.fancy_display() + ); let records = find_package_records( &project .env_root @@ -214,6 +221,7 @@ pub async fn list_global_environments( envs_changes: Option<&EnvChanges>, regex: Option, ) -> miette::Result<()> { + tracing::warn!("Foobar"); let mut project_envs = project.environments().clone(); project_envs.sort_by(|a, _, b, _| a.to_string().cmp(&b.to_string())); @@ -244,7 +252,7 @@ pub async fn list_global_environments( for (idx, (env_name, env)) in project_envs.iter().enumerate() { let env_dir = project.env_root.path().join(env_name.as_str()); let conda_meta = env_dir.join(consts::CONDA_META_DIR); - let records = find_package_records(&conda_meta).await?; + let package_ids = find_linked_packages(&conda_meta).into_diagnostic()?; let last = (idx + 1) == len; @@ -273,15 +281,15 @@ pub async fn list_global_environments( .iter() .any(|(pkg_name, _spec)| pkg_name.as_normalized() != env_name.as_str()) { - if let Some(env_package) = records.iter().find(|rec| { - rec.repodata_record.package_record.name.as_normalized() == env_name.as_str() - }) { + if let Some(package) = package_ids + .iter() + .find(|pid| pid.name.as_normalized() == env_name.as_str()) + { // output the environment name and version message.push_str(&format!( " {}: {} {}", env_name.fancy_display(), - console::style(env_package.repodata_record.package_record.version.clone()) - .blue(), + console::style(package.version.clone()).blue(), state )); } else { @@ -295,9 +303,9 @@ pub async fn list_global_environments( if let Some(dep_message) = format_dependencies( env_name.as_str(), &env.dependencies, - &records, + &package_ids, last, - !env.exposed.is_empty(), + !env.exposed().is_empty(), ) { message.push_str(&dep_message); } @@ -340,7 +348,7 @@ fn display_dependency(name: &PackageName, version: Option) -> String { fn format_dependencies( env_name: &str, dependencies: &IndexMap, - records: &[PrefixRecord], + records: &[PackageIdentifier], last: bool, more: bool, ) -> Option { @@ -353,11 +361,8 @@ fn format_dependencies( .map(|(name, _spec)| { let version = records .iter() - .find(|rec| { - rec.repodata_record.package_record.name.as_normalized() - == name.as_normalized() - }) - .map(|rec| rec.repodata_record.package_record.version.version().clone()); + .find(|pid| pid.name.as_normalized() == name.as_normalized()) + .map(|pid| pid.version.clone()); display_dependency(name, version) }) .join(", "); diff --git a/src/prefix.rs b/src/prefix.rs index e17d93d2c..8f46edbb5 100644 --- a/src/prefix.rs +++ b/src/prefix.rs @@ -83,7 +83,7 @@ impl Prefix { } } } - + tracing::warn!("Parsing '{}'", path.display()); // Spawn loading on another thread let future = tokio::task::spawn_blocking(move || { PrefixRecord::from_path(&path)