From b8fb046bd7c4cd28598bcce9f3955d834ea5d008 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 19 Aug 2026 23:45:38 +0900 Subject: perf(semver): return the memoized interval collection by handle Intervals::get() memoizes generateIntervals() results, but the port deep-cloned the IntervalCollection out of the cache on every hit, where PHP hands the array back by copy-on-write. On `require laravel/laravel` that is 282k calls, 99% of them hits. Store and return Arc so a hit costs a refcount bump. Co-Authored-By: Claude Opus 5 (1M context) --- crates/shirabe-semver/src/intervals.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/shirabe-semver/src/intervals.rs b/crates/shirabe-semver/src/intervals.rs index 9199b13b..101ba05c 100644 --- a/crates/shirabe-semver/src/intervals.rs +++ b/crates/shirabe-semver/src/intervals.rs @@ -8,7 +8,7 @@ use crate::constraint::SimpleConstraint; use crate::interval::{DevConstraintSet, Interval}; use indexmap::IndexMap; use shirabe_php_shim::{CmpOp, array_unique, version_compare, version_compare_ordering}; -use std::sync::{Mutex, OnceLock}; +use std::sync::{Arc, Mutex, OnceLock}; #[derive(Debug, Clone)] pub struct IntervalCollection { @@ -16,9 +16,10 @@ pub struct IntervalCollection { pub branches: DevConstraintSet, } -static INTERVALS_CACHE: OnceLock>> = OnceLock::new(); +static INTERVALS_CACHE: OnceLock>>> = + OnceLock::new(); -fn intervals_cache() -> &'static Mutex> { +fn intervals_cache() -> &'static Mutex>> { INTERVALS_CACHE.get_or_init(|| Mutex::new(IndexMap::new())) } @@ -289,21 +290,21 @@ impl Intervals { Ok(MatchNoneConstraint::new(None).into()) } - pub fn get(constraint: &AnyConstraint) -> anyhow::Result { + pub fn get(constraint: &AnyConstraint) -> anyhow::Result> { let key = constraint.to_string(); { let cache = intervals_cache().lock().unwrap(); if let Some(cached) = cache.get(&key) { - return Ok(cached.clone()); + return Ok(Arc::clone(cached)); } } - let result = Self::generate_intervals(constraint, false)?; + let result = Arc::new(Self::generate_intervals(constraint, false)?); { let mut cache = intervals_cache().lock().unwrap(); - cache.insert(key, result.clone()); + cache.insert(key, Arc::clone(&result)); } Ok(result) @@ -347,8 +348,8 @@ impl Intervals { let mut constraint_branches: Vec = Vec::new(); for c in sub_constraints { let res = Self::get(c)?; - numeric_groups.push(res.numeric); - constraint_branches.push(res.branches); + numeric_groups.push(res.numeric.clone()); + constraint_branches.push(res.branches.clone()); } let mut branches = if multi.is_disjunctive_mc() { -- cgit v1.3.1-4-g156e