perf: reduce redundant lookups and file I/O in generation hot paths (#1757)

- Convert usedMethods from list to hash map for O(1) dedup lookups
- Cache getRelationTypes() and getRelationReturnTypes() per command run
- Reuse SplFileObject instances by filename instead of re-opening per method
- Cache ContextFactory results per declaring class across docblock helpers

Benchmarked with hyperfine (10 runs, 2 warmup): 1.37x faster (~27%).
This commit is contained in:
Pieter Willekens
2026-02-10 15:18:58 +01:00
committed by GitHub
parent 148f956272
commit 5aca186d92
2 changed files with 65 additions and 28 deletions
+12 -11
View File
@@ -101,7 +101,7 @@ class Alias
}
if ($facade === '\Illuminate\Database\Eloquent\Model') {
$this->usedMethods = ['decrement', 'increment'];
$this->usedMethods = ['decrement' => true, 'increment' => true];
}
}
@@ -381,7 +381,7 @@ class Alias
$method = new \ReflectionMethod($className, $name);
$class = new ReflectionClass($className);
if (!in_array($magic, $this->usedMethods)) {
if (!isset($this->usedMethods[$magic])) {
if ($class !== $this->root) {
$this->methods[] = new Method(
$method,
@@ -393,7 +393,7 @@ class Alias
$this->getTemplateNames()
);
}
$this->usedMethods[] = $magic;
$this->usedMethods[$magic] = true;
}
}
}
@@ -410,7 +410,7 @@ class Alias
$methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
if ($methods) {
foreach ($methods as $method) {
if (!in_array($method->name, $this->usedMethods)) {
if (!isset($this->usedMethods[$method->name])) {
// Only add the methods to the output when the root is not the same as the class.
// And don't add the __*() methods
if ($this->extends !== $class && substr($method->name, 0, 2) !== '__') {
@@ -424,7 +424,7 @@ class Alias
$this->getTemplateNames(),
);
}
$this->usedMethods[] = $method->name;
$this->usedMethods[$method->name] = true;
}
}
}
@@ -435,7 +435,7 @@ class Alias
$properties = $reflection->getStaticProperties();
$macros = isset($properties['macros']) ? $properties['macros'] : [];
foreach ($macros as $macro_name => $macro_func) {
if (!in_array($macro_name, $this->usedMethods)) {
if (!isset($this->usedMethods[$macro_name])) {
try {
$method = $this->getMacroFunction($macro_func);
} catch (Throwable $e) {
@@ -451,7 +451,7 @@ class Alias
$this->classAliases,
$this->getReturnTypeNormalizers($reflection)
);
$this->usedMethods[] = $macro_name;
$this->usedMethods[$macro_name] = true;
}
}
}
@@ -589,12 +589,13 @@ class Alias
*/
protected function removeDuplicateMethodsFromPhpDoc()
{
$methodNames = array_map(function (Method $method) {
return $method->getName();
}, $this->getMethods());
$methodNames = [];
foreach ($this->getMethods() as $method) {
$methodNames[$method->getName()] = true;
}
foreach ($this->phpdoc->getTags() as $tag) {
if ($tag instanceof MethodTag && in_array($tag->getMethodName(), $methodNames)) {
if ($tag instanceof MethodTag && isset($methodNames[$tag->getMethodName()])) {
$this->phpdoc->deleteTag($tag);
}
}