Skip to content

Commit a0721fd

Browse files
minor #54253 [VarExporter] Improve performance when creating lazy objects (nicolas-grekas)
This PR was merged into the 7.1 branch. Discussion ---------- [VarExporter] Improve performance when creating lazy objects | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | no | New feature? | no | Deprecations? | no | Issues | - | License | MIT Creating lazy objects can happen in a tight loop, and then, this has measurable benefits. Found while working on doctrine/orm#11087 Commits ------- bf4cb39 [VarExporter] Improve performance when creating lazy objects
2 parents 3fdc2c9 + bf4cb39 commit a0721fd

File tree

4 files changed

+42
-27
lines changed

4 files changed

+42
-27
lines changed

src/Symfony/Component/VarExporter/Internal/LazyObjectRegistry.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ public static function getClassResetters($class)
7676
}, null, $scope);
7777
}
7878

79-
$resetters[] = static function ($instance, $skippedProperties) {
80-
foreach ((array) $instance as $name => $value) {
81-
if ("\0" !== ($name[0] ?? '') && !\array_key_exists($name, $skippedProperties)) {
82-
unset($instance->$name);
83-
}
84-
}
85-
};
86-
8779
return $resetters;
8880
}
8981

src/Symfony/Component/VarExporter/Internal/LazyObjectState.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,20 @@ class LazyObjectState
2727
public const STATUS_INITIALIZED_FULL = 3;
2828
public const STATUS_INITIALIZED_PARTIAL = 4;
2929

30-
/**
31-
* @var array<string, true>
32-
*/
33-
public readonly array $skippedProperties;
34-
3530
/**
3631
* @var self::STATUS_*
3732
*/
38-
public int $status = 0;
33+
public int $status = self::STATUS_UNINITIALIZED_FULL;
3934

4035
public object $realInstance;
4136

42-
public function __construct(public readonly \Closure $initializer, $skippedProperties = [])
43-
{
44-
$this->skippedProperties = $skippedProperties;
45-
$this->status = self::STATUS_UNINITIALIZED_FULL;
37+
/**
38+
* @param array<string, true> $skippedProperties
39+
*/
40+
public function __construct(
41+
public readonly \Closure $initializer,
42+
public readonly array $skippedProperties = [],
43+
) {
4644
}
4745

4846
public function initialize($instance, $propertyName, $propertyScope)
@@ -88,6 +86,12 @@ public function reset($instance): void
8886
$reset($instance, $skippedProperties);
8987
}
9088

89+
foreach ((array) $instance as $name => $value) {
90+
if ("\0" !== ($name[0] ?? '') && !\array_key_exists($name, $skippedProperties)) {
91+
unset($instance->$name);
92+
}
93+
}
94+
9195
$this->status = self::STATUS_UNINITIALIZED_FULL;
9296
}
9397
}

src/Symfony/Component/VarExporter/LazyGhostTrait.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,24 @@ public static function createLazyGhost(\Closure $initializer, ?array $skippedPro
3535
{
3636
if (self::class !== $class = $instance ? $instance::class : static::class) {
3737
$skippedProperties["\0".self::class."\0lazyObjectState"] = true;
38-
} elseif (\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
39-
Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
4038
}
4139

42-
$instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor();
43-
Registry::$defaultProperties[$class] ??= (array) $instance;
40+
if (!isset(Registry::$defaultProperties[$class])) {
41+
Registry::$classReflectors[$class] ??= new \ReflectionClass($class);
42+
$instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
43+
Registry::$defaultProperties[$class] ??= (array) $instance;
44+
Registry::$classResetters[$class] ??= Registry::getClassResetters($class);
45+
46+
if (self::class === $class && \defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
47+
Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
48+
}
49+
} else {
50+
$instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
51+
}
52+
4453
$instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []);
4554

46-
foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
55+
foreach (Registry::$classResetters[$class] as $reset) {
4756
$reset($instance, $skippedProperties);
4857
}
4958

src/Symfony/Component/VarExporter/LazyProxyTrait.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,24 @@ public static function createLazyProxy(\Closure $initializer, ?object $instance
3131
{
3232
if (self::class !== $class = $instance ? $instance::class : static::class) {
3333
$skippedProperties = ["\0".self::class."\0lazyObjectState" => true];
34-
} elseif (\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
35-
Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
3634
}
3735

38-
$instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor();
36+
if (!isset(Registry::$defaultProperties[$class])) {
37+
Registry::$classReflectors[$class] ??= new \ReflectionClass($class);
38+
$instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
39+
Registry::$defaultProperties[$class] ??= (array) $instance;
40+
Registry::$classResetters[$class] ??= Registry::getClassResetters($class);
41+
42+
if (self::class === $class && \defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
43+
Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
44+
}
45+
} else {
46+
$instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
47+
}
48+
3949
$instance->lazyObjectState = new LazyObjectState($initializer);
4050

41-
foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
51+
foreach (Registry::$classResetters[$class] as $reset) {
4252
$reset($instance, $skippedProperties ??= []);
4353
}
4454

0 commit comments

Comments
 (0)