From e3fb8bf9b86c8f82f5b29db57cf2c714e8b5e1ac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 05:06:15 +0000 Subject: [PATCH 1/3] Initial plan From cdcc3e2ea07f2ab4e6c82d5cd65aff1aa433e5e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 05:24:53 +0000 Subject: [PATCH 2/3] Optimize array lookups - replace in_array with isset for O(1) performance Co-authored-by: Yurunsoft <20104656+Yurunsoft@users.noreply.github.com> --- .../Annotation/Model/AnnotationRelation.php | 16 +++++++++++---- src/Bean/AnnotationParser.php | 20 ++++++++++++++++--- src/Db/Query/Query.php | 3 ++- src/Model/Meta.php | 4 +++- src/Validate/Validator.php | 4 +++- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/Bean/Annotation/Model/AnnotationRelation.php b/src/Bean/Annotation/Model/AnnotationRelation.php index 03319e4127..9919f14e6f 100644 --- a/src/Bean/Annotation/Model/AnnotationRelation.php +++ b/src/Bean/Annotation/Model/AnnotationRelation.php @@ -374,12 +374,14 @@ public function removeClassRelation($className): void { $classRelations = &$this->classRelations; $className = (array) $className; + // Optimize lookup by using array keys instead of in_array + $classNameMap = array_flip($className); foreach ($classRelations as $annotationClass => &$list) { $haveUnset = false; foreach ($list as $i => $item) { - if (\in_array($item->getClass(), $className)) + if (isset($classNameMap[$item->getClass()])) { unset($list[$i]); $haveUnset = true; @@ -402,12 +404,14 @@ public function removeMethodRelation(string $className, $methodName): void { $methodRelations = &$this->methodRelations; $methodName = (array) $methodName; + // Optimize lookup by using array keys instead of in_array + $methodNameMap = array_flip($methodName); foreach ($methodRelations as $annotationClass => &$list) { $haveUnset = false; foreach ($list as $i => $item) { - if ($item->getClass() === $className && \in_array($item->getMethod(), $methodName)) + if ($item->getClass() === $className && isset($methodNameMap[$item->getMethod()])) { unset($list[$i]); $haveUnset = true; @@ -430,12 +434,14 @@ public function removePropertyRelation(string $className, $propertyName): void { $propertyRelations = &$this->propertyRelations; $propertyName = (array) $propertyName; + // Optimize lookup by using array keys instead of in_array + $propertyNameMap = array_flip($propertyName); foreach ($propertyRelations as $annotationClass => &$list) { $haveUnset = false; foreach ($list as $i => $item) { - if ($item->getClass() === $className && \in_array($item->getProperty(), $propertyName)) + if ($item->getClass() === $className && isset($propertyNameMap[$item->getProperty()])) { unset($list[$i]); $haveUnset = true; @@ -458,12 +464,14 @@ public function removeConstantRelation(string $className, $constantName): void { $constantRelations = &$this->constantRelations; $constantName = (array) $constantName; + // Optimize lookup by using array keys instead of in_array + $constantNameMap = array_flip($constantName); foreach ($constantRelations as $annotationClass => &$list) { $haveUnset = false; foreach ($list as $i => $item) { - if ($item->getClass() === $className && \in_array($item->getConstant(), $constantName)) + if ($item->getClass() === $className && isset($constantNameMap[$item->getConstant()])) { unset($list[$i]); $haveUnset = true; diff --git a/src/Bean/AnnotationParser.php b/src/Bean/AnnotationParser.php index be42ed4c61..dc10d03c85 100644 --- a/src/Bean/AnnotationParser.php +++ b/src/Bean/AnnotationParser.php @@ -33,6 +33,13 @@ class AnnotationParser */ private array $classes = []; + /** + * 文件名到类名的反向映射. + * + * @var array + */ + private array $fileToClassMap = []; + /** * 处理器类名映射. */ @@ -62,14 +69,14 @@ class AnnotationParser public function __construct() { - $this->initIncludeFiles = get_included_files(); + $this->initIncludeFiles = array_flip(get_included_files()); $this->enableAnnotationCache = Config::get('@app.imi.annotation.cache', false); AnnotationReader::addGlobalIgnoredName('noRector'); } public function parse(string $className, bool $transaction = true, ?string $fileName = null): bool { - $autoload = (null === $fileName) || (!isset($this->files[$fileName]) && (!\in_array($fileName, $this->initIncludeFiles))); + $autoload = (null === $fileName) || (!isset($this->files[$fileName]) && !isset($this->initIncludeFiles[$fileName])); if (!class_exists($className, $autoload) && !interface_exists($className, false) && !trait_exists($className, false)) { if ($autoload && !isset($this->files[$fileName]) && null !== $fileName) @@ -151,6 +158,7 @@ public function parseClass(\ReflectionClass $ref): void { $fileName = $ref->getFileName(); $thisClasses[$className] = $fileName; + $this->fileToClassMap[$fileName] = $className; // @Inherit 注解继承父级的注解 $hasInherit = false; @@ -245,6 +253,7 @@ public function parseMethod(\ReflectionClass $ref, \ReflectionMethod $method): v { $fileName = $ref->getFileName(); $thisClasses[$className] = $fileName; + $this->fileToClassMap[$fileName] = $className; // @Inherit 注解继承父级的注解 $hasInherit = false; @@ -339,6 +348,7 @@ public function parseProp(\ReflectionClass $ref, \ReflectionProperty $prop): voi { $fileName = $ref->getFileName(); $thisClasses[$className] = $fileName; + $this->fileToClassMap[$fileName] = $className; // @Inherit 注解继承父级的注解 $hasInherit = false; @@ -432,6 +442,7 @@ public function parseConst(\ReflectionClass $ref, \ReflectionClassConstant $cons { $fileName = $ref->getFileName(); $thisClasses[$className] = $fileName; + $this->fileToClassMap[$fileName] = $className; // @Inherit 注解继承父级的注解 $hasInherit = false; @@ -516,6 +527,7 @@ public function parseMethodParameter(\ReflectionClass $ref, \ReflectionMethod $r { $fileName = $ref->getFileName(); $thisClasses[$className] = $fileName; + $this->fileToClassMap[$fileName] = $className; // @Inherit 注解继承父级的注解 $hasInherit = false; @@ -764,7 +776,7 @@ public function parseIncr(array $files): void { unset($thisFiles[$file]); } - if (!($className = array_search($file, $thisClasses))) + if (!($className = $this->fileToClassMap[$file] ?? false)) { if (is_file($file)) { @@ -813,6 +825,7 @@ public function getStoreData(): array return [ $this->files, $this->classes, + $this->fileToClassMap, ]; } @@ -823,6 +836,7 @@ public function loadStoreData(array $data): void { $this->files = $data[0]; $this->classes = $data[1]; + $this->fileToClassMap = $data[2] ?? []; } /** diff --git a/src/Db/Query/Query.php b/src/Db/Query/Query.php index d84befe8d3..067da42bd4 100644 --- a/src/Db/Query/Query.php +++ b/src/Db/Query/Query.php @@ -1283,7 +1283,8 @@ public function column($fields, ?string $key = null): array { $key = null; } - if ($key && !\in_array($key, $fields)) + // Optimize by converting to associative array for O(1) lookup + if ($key && !isset(array_flip($fields)[$key])) { $fields[] = $key; } diff --git a/src/Model/Meta.php b/src/Model/Meta.php index cc88b91ca9..499d0b106e 100644 --- a/src/Model/Meta.php +++ b/src/Model/Meta.php @@ -339,6 +339,8 @@ public function __construct(string $modelClass, bool $inherit = false) $this->bean = $entity->bean ?? true; $this->incrUpdate = $entity->incrUpdate ?? false; $serializableFieldNames = $parsedSerializableFieldNames = $fieldNames = []; + // Optimize field lookup by using array keys instead of in_array + $serializableFieldsMap = $serializables ? array_flip($serializables->fields) : []; foreach ($fields as $fieldName => $column) { $fieldNames[] = $fieldName; @@ -366,7 +368,7 @@ public function __construct(string $modelClass, bool $inherit = false) } elseif ($serializables) { - if (\in_array($name, $serializables->fields)) + if (isset($serializableFieldsMap[$name])) { // 在黑名单中的字段剔除 if ('deny' === $serializables->mode) diff --git a/src/Validate/Validator.php b/src/Validate/Validator.php index 896864dce0..66efca3ec1 100644 --- a/src/Validate/Validator.php +++ b/src/Validate/Validator.php @@ -196,6 +196,8 @@ protected function __validateAll(&$data, bool $break): bool $thisResults = []; $result = true; $sceneOption = $this->scene[$this->currentScene] ?? null; + // Optimize field lookup by using array keys instead of in_array + $sceneOptionMap = $sceneOption ? array_flip($sceneOption) : null; foreach ($this->rules as $annotation) { if (!$annotation instanceof Condition) @@ -203,7 +205,7 @@ protected function __validateAll(&$data, bool $break): bool continue; } $annotationName = $annotation->name; - if ($sceneOption && !\in_array($annotationName, $sceneOption)) + if ($sceneOptionMap && !isset($sceneOptionMap[$annotationName])) { continue; } From 633d4e0af0c76f38278c151f51fd3c62a2cca992 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 05:33:25 +0000 Subject: [PATCH 3/3] Fix Query.php - pre-compute array_flip outside conditional Co-authored-by: Yurunsoft <20104656+Yurunsoft@users.noreply.github.com> --- src/Db/Query/Query.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Db/Query/Query.php b/src/Db/Query/Query.php index 067da42bd4..b82cdab5f9 100644 --- a/src/Db/Query/Query.php +++ b/src/Db/Query/Query.php @@ -1284,7 +1284,8 @@ public function column($fields, ?string $key = null): array $key = null; } // Optimize by converting to associative array for O(1) lookup - if ($key && !isset(array_flip($fields)[$key])) + $fieldsMap = array_flip($fields); + if ($key && !isset($fieldsMap[$key])) { $fields[] = $key; }