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
commit325c75b58c05e9ef8fed51c05609dfc2bfed112d (patch)
treed96f79864ebf51a164da50c4dd0d062c3fd70a6b /crates/shirabe-semver/src
parent95bb4d31909367597f71e8e0c90e008d25945dd3 (diff)
downloadphp-shirabe-325c75b58c05e9ef8fed51c05609dfc2bfed112d.tar.gz
php-shirabe-325c75b58c05e9ef8fed51c05609dfc2bfed112d.tar.zst
php-shirabe-325c75b58c05e9ef8fed51c05609dfc2bfed112d.zip
perf(semver): memoize MultiConstraint's string form
composer/semver memoizes MultiConstraint::__toString() into $this->string, but the port recomputed it on every call. On `require laravel/laravel` that meant 837k stringifications visiting 1.7M child constraints, all of them feeding the CompilingMatcher and Intervals cache keys. 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/constraint/multi_constraint.rs12
1 files changed, 9 insertions, 3 deletions
diff --git a/crates/shirabe-semver/src/constraint/multi_constraint.rs b/crates/shirabe-semver/src/constraint/multi_constraint.rs
index 4e9b8cf5..30c2edd6 100644
--- a/crates/shirabe-semver/src/constraint/multi_constraint.rs
+++ b/crates/shirabe-semver/src/constraint/multi_constraint.rs
@@ -4,11 +4,13 @@ use crate::constraint::AnyConstraint;
use crate::constraint::Bound;
use crate::constraint::MatchAllConstraint;
use shirabe_php_shim::CmpOp;
+use std::sync::OnceLock;
#[derive(Debug, Clone)]
pub struct MultiConstraint {
pub(crate) constraints: Vec<AnyConstraint>,
pub(crate) pretty_string: Option<String>,
+ string: OnceLock<String>,
pub(crate) conjunctive: bool,
}
@@ -28,6 +30,7 @@ impl MultiConstraint {
Self {
constraints,
pretty_string,
+ string: OnceLock::new(),
conjunctive,
}
}
@@ -251,8 +254,11 @@ impl MultiConstraint {
impl std::fmt::Display for MultiConstraint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let parts: Vec<String> = self.constraints.iter().map(|c| c.to_string()).collect();
- let sep = if self.conjunctive { " " } else { " || " };
- write!(f, "[{}]", parts.join(sep))
+ let string = self.string.get_or_init(|| {
+ let parts: Vec<String> = self.constraints.iter().map(|c| c.to_string()).collect();
+ let sep = if self.conjunctive { " " } else { " || " };
+ format!("[{}]", parts.join(sep))
+ });
+ f.write_str(string)
}
}