aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-semver/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-19 23:45:38 +0900
committernsfisis <nsfisis@gmail.com>2026-08-19 23:45:38 +0900
commitb8fb046bd7c4cd28598bcce9f3955d834ea5d008 (patch)
tree33237ee7c09bf36de8c54fc069371976660db663 /crates/shirabe-semver/src
parent325c75b58c05e9ef8fed51c05609dfc2bfed112d (diff)
downloadphp-shirabe-b8fb046bd7c4cd28598bcce9f3955d834ea5d008.tar.gz
php-shirabe-b8fb046bd7c4cd28598bcce9f3955d834ea5d008.tar.zst
php-shirabe-b8fb046bd7c4cd28598bcce9f3955d834ea5d008.zip
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<IntervalCollection> so a hit costs a refcount bump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-semver/src')
-rw-r--r--crates/shirabe-semver/src/intervals.rs19
1 files 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<Mutex<IndexMap<String, IntervalCollection>>> = OnceLock::new();
+static INTERVALS_CACHE: OnceLock<Mutex<IndexMap<String, Arc<IntervalCollection>>>> =
+ OnceLock::new();
-fn intervals_cache() -> &'static Mutex<IndexMap<String, IntervalCollection>> {
+fn intervals_cache() -> &'static Mutex<IndexMap<String, Arc<IntervalCollection>>> {
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<IntervalCollection> {
+ pub fn get(constraint: &AnyConstraint) -> anyhow::Result<Arc<IntervalCollection>> {
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<DevConstraintSet> = 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() {