diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-07-20 23:30:19 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-07-20 23:30:19 +0900 |
| commit | 641451481bcff596a7db52b5f2bcbeaddbeb1681 (patch) | |
| tree | 364e24bf182efe755f6ece9278aafc0ac99b578a /crates | |
| parent | 2862d2da275a672f22485f5d1db3550248b20251 (diff) | |
| download | php-shirabe-641451481bcff596a7db52b5f2bcbeaddbeb1681.tar.gz php-shirabe-641451481bcff596a7db52b5f2bcbeaddbeb1681.tar.zst php-shirabe-641451481bcff596a7db52b5f2bcbeaddbeb1681.zip | |
perf(composer-repository): avoid redundant clones when checking security advisories
get_security_advisories cloned each package's full metadata blob
(hundreds of versions for popular packages) just to peek at its
"security-advisories" field. Same pattern already fixed in
load_async_packages by 2862d2da; move ownership through pattern
matches and IndexMap::shift_remove instead.
Measured with laravel/laravel create-project: response processing in
the security-advisories metadata branch drops ~80% (236ms -> 48ms),
and the whole run_security_advisory_filter phase drops from ~420-500ms
to ~250-270ms. End-to-end, shirabe now matches or edges out upstream
Composer (6.57s vs 6.85s in this run) instead of trailing by ~1.2s.
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/shirabe/src/repository/composer_repository.rs | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs index ab83ace2..66d530c4 100644 --- a/crates/shirabe/src/repository/composer_repository.rs +++ b/crates/shirabe/src/repository/composer_repository.rs @@ -996,31 +996,30 @@ impl ComposerRepository { let spec = spec?; // [$response] = $spec; - let response = spec - .as_list() - .and_then(|l| l.first()) - .cloned() - .unwrap_or(PhpMixed::Null); - let response_arr = match response.as_array() { - Some(a) => a.clone(), - None => continue, + let response = match spec { + PhpMixed::List(mut l) if !l.is_empty() => l.remove(0), + _ => PhpMixed::Null, }; - let sec_advs_arr = match response_arr.get("security-advisories") { - Some(PhpMixed::List(l)) => l.clone(), - Some(PhpMixed::Array(a)) => a.values().cloned().collect(), + // Takes ownership out of response instead of cloning: response is local to this + // iteration's own package metadata and is not read again afterwards. + let mut response_arr = match response { + PhpMixed::Array(a) => a, + _ => continue, + }; + let sec_advs_arr = match response_arr.shift_remove("security-advisories") { + Some(PhpMixed::List(l)) => l, + Some(PhpMixed::Array(a)) => a.into_values().collect(), _ => continue, }; names_found.insert(name.clone(), true); if !sec_advs_arr.is_empty() { let mut entries: Vec<AnySecurityAdvisory> = Vec::new(); - for data_mixed in sec_advs_arr.iter() { - if let Some(data) = data_mixed.as_array() { - let data_map: IndexMap<String, PhpMixed> = - data.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); - if let Some(adv) = create(&data_map, &name, &package_constraint_map)? { - entries.push(adv); - } + for data_mixed in sec_advs_arr.into_iter() { + if let PhpMixed::Array(data_map) = data_mixed + && let Some(adv) = create(&data_map, &name, &package_constraint_map)? + { + entries.push(adv); } } advisories.insert(name.clone(), entries); |
