Skip to content

Commit 971f07f

Browse files
committed
perf(attribute-analyzer): optimize performance and memory usage with caching
- Add class metadata caching to avoid repeated reflection - Improve memory management and garbage collection - Add comprehensive benchmarking suite BREAKING CHANGE: OptimizedAttributeAnalyzer now implements AttributeAnalyzerContract directly Performance improvements: - Memory usage reduced by caching reflection metadata - Processing time improved with optimized property access - Better garbage collection handling - More accurate benchmarking with warmup cycles
1 parent 84566f7 commit 971f07f

File tree

3 files changed

+647
-289
lines changed

3 files changed

+647
-289
lines changed

src/AttributeAnalyzer.php

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,75 @@
77
use KaririCode\PropertyInspector\Contract\AttributeAnalyzer as AttributeAnalyzerContract;
88
use KaririCode\PropertyInspector\Exception\PropertyInspectionException;
99

10-
final readonly class AttributeAnalyzer implements AttributeAnalyzerContract
10+
final class AttributeAnalyzer implements AttributeAnalyzerContract
1111
{
12-
public function __construct(private string $attributeClass)
12+
private array $cache = [];
13+
14+
public function __construct(private readonly string $attributeClass)
1315
{
1416
}
1517

1618
public function analyzeObject(object $object): array
1719
{
1820
try {
19-
$results = [];
20-
$reflection = new \ReflectionClass($object);
21-
22-
foreach ($reflection->getProperties() as $property) {
23-
$propertyResult = $this->analyzeProperty($object, $property);
24-
if (null !== $propertyResult) {
25-
$results[$property->getName()] = $propertyResult;
26-
}
21+
$className = $object::class;
22+
23+
// Usar cache se disponível
24+
if (!isset($this->cache[$className])) {
25+
$this->cacheObjectMetadata($object);
2726
}
2827

29-
return $results;
28+
return $this->extractValues($object);
3029
} catch (\ReflectionException $e) {
3130
throw new PropertyInspectionException('Failed to analyze object: ' . $e->getMessage(), 0, $e);
3231
} catch (\Error $e) {
3332
throw new PropertyInspectionException('An error occurred during object analysis: ' . $e->getMessage(), 0, $e);
3433
}
3534
}
3635

37-
private function analyzeProperty(object $object, \ReflectionProperty $property): ?array
36+
private function cacheObjectMetadata(object $object): void
3837
{
39-
$attributes = $property->getAttributes($this->attributeClass, \ReflectionAttribute::IS_INSTANCEOF);
40-
if (empty($attributes)) {
41-
return null;
38+
$className = $object::class;
39+
$reflection = new \ReflectionClass($object);
40+
$cachedProperties = [];
41+
42+
foreach ($reflection->getProperties() as $property) {
43+
$attributes = $property->getAttributes($this->attributeClass, \ReflectionAttribute::IS_INSTANCEOF);
44+
45+
if (!empty($attributes)) {
46+
$property->setAccessible(true);
47+
$attributeInstances = array_map(
48+
static fn (\ReflectionAttribute $attr): object => $attr->newInstance(),
49+
$attributes
50+
);
51+
52+
$cachedProperties[$property->getName()] = [
53+
'attributes' => $attributeInstances,
54+
'property' => $property,
55+
];
56+
}
4257
}
4358

44-
$property->setAccessible(true);
45-
$propertyValue = $property->getValue($object);
59+
$this->cache[$className] = $cachedProperties;
60+
}
4661

47-
$attributeInstances = array_map(
48-
static fn (\ReflectionAttribute $attr): object => $attr->newInstance(),
49-
$attributes
50-
);
62+
private function extractValues(object $object): array
63+
{
64+
$results = [];
65+
$className = $object::class;
66+
67+
foreach ($this->cache[$className] as $propertyName => $data) {
68+
$results[$propertyName] = [
69+
'value' => $data['property']->getValue($object),
70+
'attributes' => $data['attributes'],
71+
];
72+
}
5173

52-
return [
53-
'value' => $propertyValue,
54-
'attributes' => $attributeInstances,
55-
];
74+
return $results;
75+
}
76+
77+
public function clearCache(): void
78+
{
79+
$this->cache = [];
5680
}
5781
}

0 commit comments

Comments
 (0)