diff options
6 files changed, 45 insertions, 26 deletions
diff --git a/crates/shirabe-semver/src/compiling_matcher.rs b/crates/shirabe-semver/src/compiling_matcher.rs index 0d637037..66e9f98c 100644 --- a/crates/shirabe-semver/src/compiling_matcher.rs +++ b/crates/shirabe-semver/src/compiling_matcher.rs @@ -4,9 +4,15 @@ use crate::constraint::AnyConstraint; use crate::constraint::SimpleConstraint; use indexmap::IndexMap; use shirabe_php_shim::CmpOp; +use std::fmt::Write as _; use std::sync::Mutex; use std::sync::OnceLock; +thread_local! { + static KEY_BUFFER: std::cell::RefCell<String> = + const { std::cell::RefCell::new(String::new()) }; +} + // Rust does not support eval(), so the compiled checker path is always disabled. // The COMPILED_CHECKER_CACHE is retained structurally but never populated. static COMPILED_CHECKER_CACHE: OnceLock< @@ -31,28 +37,41 @@ impl CompilingMatcher { Self::compiled_checker_cache().lock().unwrap().clear(); } - pub fn r#match(constraint: &AnyConstraint, operator: CmpOp, version: String) -> bool { - let result_cache_key = format!( - "{}{};{}", - SimpleConstraint::get_operator_constant(operator), - constraint, - version - ); + pub fn r#match(constraint: &AnyConstraint, operator: CmpOp, version: &str) -> bool { + #[derive(Debug)] + enum CacheResult { + Hit(bool), + Miss(String), + } + + // The key is built into a reused buffer and only copied when it has to be stored, so a + // cache hit allocates nothing. + let cached = KEY_BUFFER.with_borrow_mut(|key| { + key.clear(); + let _ = write!( + key, + "{}{};{}", + SimpleConstraint::get_operator_constant(operator), + constraint, + version + ); - { let cache = Self::result_cache().lock().unwrap(); - if let Some(&result) = cache.get(&result_cache_key) { - return result; + match cache.get(key.as_str()) { + Some(&result) => CacheResult::Hit(result), + None => CacheResult::Miss(key.clone()), } - } + }); + let key = match cached { + CacheResult::Hit(result) => return result, + CacheResult::Miss(key) => key, + }; - let result = - constraint.matches(&SimpleConstraint::new(operator.to_string(), version, None).into()); + let result = constraint.matches( + &SimpleConstraint::new(operator.to_string(), version.to_string(), None).into(), + ); - Self::result_cache() - .lock() - .unwrap() - .insert(result_cache_key, result); + Self::result_cache().lock().unwrap().insert(key, result); result } } diff --git a/crates/shirabe/src/dependency_resolver/default_policy.rs b/crates/shirabe/src/dependency_resolver/default_policy.rs index f753dc48..fee54a90 100644 --- a/crates/shirabe/src/dependency_resolver/default_policy.rs +++ b/crates/shirabe/src/dependency_resolver/default_policy.rs @@ -203,7 +203,7 @@ impl PolicyInterface for DefaultPolicy { CompilingMatcher::r#match( &SimpleConstraint::new(operator.to_string(), b.get_version(), None).into(), CmpOp::Eq, - a.get_version(), + &a.get_version(), ) } diff --git a/crates/shirabe/src/dependency_resolver/pool.rs b/crates/shirabe/src/dependency_resolver/pool.rs index c12f819d..7ec6196b 100644 --- a/crates/shirabe/src/dependency_resolver/pool.rs +++ b/crates/shirabe/src/dependency_resolver/pool.rs @@ -305,7 +305,7 @@ impl Pool { if candidate_name == name { return constraint.is_none() - || CompilingMatcher::r#match(constraint.unwrap(), CmpOp::Eq, candidate_version); + || CompilingMatcher::r#match(constraint.unwrap(), CmpOp::Eq, &candidate_version); } let provides = candidate.get_provides(); diff --git a/crates/shirabe/src/dependency_resolver/pool_builder.rs b/crates/shirabe/src/dependency_resolver/pool_builder.rs index a47952af..0d2b7797 100644 --- a/crates/shirabe/src/dependency_resolver/pool_builder.rs +++ b/crates/shirabe/src/dependency_resolver/pool_builder.rs @@ -286,7 +286,7 @@ impl PoolBuilder { if CompilingMatcher::r#match( &constraint, CmpOp::Eq, - package_or_alias.get_version(), + &package_or_alias.get_version(), ) { found = true; } diff --git a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs index c71feb4d..b06cdd54 100644 --- a/crates/shirabe/src/dependency_resolver/pool_optimizer.rs +++ b/crates/shirabe/src/dependency_resolver/pool_optimizer.rs @@ -156,7 +156,7 @@ impl PoolOptimizer { let constraint = irremovable_package_constraints .get(&package.get_name()) .unwrap(); - if CompilingMatcher::r#match(constraint, CmpOp::Eq, package.get_version().to_string()) { + if CompilingMatcher::r#match(constraint, CmpOp::Eq, &package.get_version()) { self.mark_package_irremovable(package.clone()); } } @@ -249,7 +249,7 @@ impl PoolOptimizer { if CompilingMatcher::r#match( require_constraint, CmpOp::Eq, - package.get_version().to_string(), + &package.get_version(), ) { group_hash_parts.push(format!( "require:{}", @@ -262,7 +262,7 @@ impl PoolOptimizer { if CompilingMatcher::r#match( link.get_constraint(), CmpOp::Eq, - package.get_version().to_string(), + &package.get_version(), ) { // Use the same hash part as the regular require hash because that's what the replacement does group_hash_parts.push(format!( @@ -280,7 +280,7 @@ impl PoolOptimizer { if CompilingMatcher::r#match( conflict_constraint, CmpOp::Eq, - package.get_version().to_string(), + &package.get_version(), ) { group_hash_parts.push(format!( "conflict:{}", @@ -601,7 +601,7 @@ impl PoolOptimizer { .and_then(|m| m.get(&id)) .map(|p| p.get_version()); if let Some(version_str) = version_str - && !CompilingMatcher::r#match(link_constraint, CmpOp::Eq, version_str) + && !CompilingMatcher::r#match(link_constraint, CmpOp::Eq, &version_str) { self.mark_package_for_removal(id); if let Some(map) = package_index.get_mut(require) { diff --git a/crates/shirabe/src/repository/composer_repository.rs b/crates/shirabe/src/repository/composer_repository.rs index ad755d50..89226e4c 100644 --- a/crates/shirabe/src/repository/composer_repository.rs +++ b/crates/shirabe/src/repository/composer_repository.rs @@ -2133,7 +2133,7 @@ impl ComposerRepository { } if let Some(c) = constraint - && !CompilingMatcher::r#match(c, CmpOp::Eq, version.clone()) + && !CompilingMatcher::r#match(c, CmpOp::Eq, version) { continue; } |
