From cd7c3fce2472656b2a1247429751e43350976677 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 19 Aug 2026 23:45:38 +0900 Subject: perf(package): hand out link maps behind Rc PackageInterface::getRequires() and friends return the array of Link objects; in PHP that is a copy-on-write array of object references, so a caller pays nothing to look at it. The port returned IndexMap by value, so every call deep-cloned the whole map, keys and constraints included. Pool building calls these accessors once per package per candidate, which put IndexMap::clone at 13.5% of `require laravel/laravel`. Store the maps as Rc> and return a handle. Callers that mutate the map clone it explicitly at the point of mutation, matching where PHP would separate the array. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/repository/filesystem_repository.rs | 4 +-- .../shirabe/src/repository/installed_repository.rs | 29 +++++++++++++--------- crates/shirabe/src/repository/repository_utils.rs | 9 +++++-- crates/shirabe/src/repository/vcs/github_driver.rs | 2 +- crates/shirabe/src/repository/vcs/gitlab_driver.rs | 2 +- 5 files changed, 28 insertions(+), 18 deletions(-) (limited to 'crates/shirabe/src/repository') diff --git a/crates/shirabe/src/repository/filesystem_repository.rs b/crates/shirabe/src/repository/filesystem_repository.rs index 54c2fa1f..5f06505a 100644 --- a/crates/shirabe/src/repository/filesystem_repository.rs +++ b/crates/shirabe/src/repository/filesystem_repository.rs @@ -510,7 +510,7 @@ impl FilesystemRepository { .as_array() .map(|m| m.contains_key(&package.get_name())) .unwrap_or(false); - for (_, replace) in package.get_replaces() { + for (_, replace) in package.get_replaces().iter() { // exclude platform replaces as when they are really there we can not check for their presence if PlatformRepository::is_platform_package(replace.get_target()) { continue; @@ -527,7 +527,7 @@ impl FilesystemRepository { is_dev_package, ); } - for (_, provide) in package.get_provides() { + for (_, provide) in package.get_provides().iter() { // exclude platform provides as when they are really there we can not check for their presence if PlatformRepository::is_platform_package(provide.get_target()) { continue; diff --git a/crates/shirabe/src/repository/installed_repository.rs b/crates/shirabe/src/repository/installed_repository.rs index 36ad510c..097fca84 100644 --- a/crates/shirabe/src/repository/installed_repository.rs +++ b/crates/shirabe/src/repository/installed_repository.rs @@ -84,8 +84,10 @@ impl InstalledRepository { continue; } - let provides_and_replaces = - array_merge_map(candidate.get_provides(), candidate.get_replaces()); + let provides_and_replaces = array_merge_map( + (*candidate.get_provides()).clone(), + (*candidate.get_replaces()).clone(), + ); for link in provides_and_replaces.values() { if name == link.get_target() && (constraint.is_none() @@ -126,12 +128,12 @@ impl InstalledRepository { } for package in self.inner.get_packages()? { - let mut links: IndexMap = package.get_requires(); + let mut links: IndexMap = (*package.get_requires()).clone(); let mut packages_in_tree = packages_found.clone(); if !invert { - for (k, v) in package.get_replaces() { - links.entry(k).or_insert(v); + for (k, v) in package.get_replaces().iter() { + links.entry(k.clone()).or_insert(v.clone()); } let needles_snapshot = needles.clone(); @@ -169,8 +171,8 @@ impl InstalledRepository { } if package.as_root().is_some() { - for (k, v) in package.get_dev_requires() { - links.entry(k).or_insert(v); + for (k, v) in package.get_dev_requires().iter() { + links.entry(k.clone()).or_insert(v.clone()); } } @@ -297,8 +299,10 @@ impl InstalledRepository { .into(); if link.get_target() != pkg.get_name().as_str() { - let replaces_and_provides = - array_merge_map(pkg.get_replaces(), pkg.get_provides()); + let replaces_and_provides = array_merge_map( + (*pkg.get_replaces()).clone(), + (*pkg.get_provides()).clone(), + ); for prov in replaces_and_provides.values() { if link.get_target() == prov.get_target() { version = prov.get_constraint().clone(); @@ -309,9 +313,10 @@ impl InstalledRepository { if !link.get_constraint().matches(&version) { if let Some(root_pkg) = root_package.as_ref() { - let mut root_reqs: IndexMap = root_pkg.get_requires(); - for (k, v) in root_pkg.get_dev_requires() { - root_reqs.entry(k).or_insert(v); + let mut root_reqs: IndexMap = + (*root_pkg.get_requires()).clone(); + for (k, v) in root_pkg.get_dev_requires().iter() { + root_reqs.entry(k.clone()).or_insert(v.clone()); } for root_req in root_reqs.values() { if pkg diff --git a/crates/shirabe/src/repository/repository_utils.rs b/crates/shirabe/src/repository/repository_utils.rs index c2997f31..3df86b05 100644 --- a/crates/shirabe/src/repository/repository_utils.rs +++ b/crates/shirabe/src/repository/repository_utils.rs @@ -16,9 +16,14 @@ impl RepositoryUtils { include_require_dev: bool, mut bucket: Vec, ) -> Vec { - let mut requires: IndexMap = requirer.get_requires(); + let mut requires: IndexMap = (*requirer.get_requires()).clone(); if include_require_dev { - requires.extend(requirer.get_dev_requires()); + requires.extend( + requirer + .get_dev_requires() + .iter() + .map(|(k, v)| (k.clone(), v.clone())), + ); } for candidate in packages { diff --git a/crates/shirabe/src/repository/vcs/github_driver.rs b/crates/shirabe/src/repository/vcs/github_driver.rs index f2b2d458..60920969 100644 --- a/crates/shirabe/src/repository/vcs/github_driver.rs +++ b/crates/shirabe/src/repository/vcs/github_driver.rs @@ -1230,7 +1230,7 @@ impl GitHubDriver { } let links = explode(",", &header); - for link in &links { + for link in links.iter() { if let Some(m) = preg_match(php_regex!(r#"{<(.+?)>; *rel="next"}"#), link) { return Some(m.get(1).unwrap_or_default().to_string()); } diff --git a/crates/shirabe/src/repository/vcs/gitlab_driver.rs b/crates/shirabe/src/repository/vcs/gitlab_driver.rs index d21a9ca1..f77eec5d 100644 --- a/crates/shirabe/src/repository/vcs/gitlab_driver.rs +++ b/crates/shirabe/src/repository/vcs/gitlab_driver.rs @@ -972,7 +972,7 @@ impl GitLabDriver { let header = response.get_header("link").unwrap_or_default(); let links = explode(",", &header); - for link in &links { + for link in links.iter() { if let Some(match_) = preg_match(php_regex!(r#"{<(.+?)>; *rel="next"}"#), link) { return Some(match_.get(1).unwrap_or_default().to_string()); } -- cgit v1.3.1-4-g156e