From feed0d4fc7fc4c6c3f54d795b02d20d87fc35310 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Sat, 12 Oct 2024 18:19:14 +0700 Subject: [PATCH] perf(`ObjectCache`): use sentinel value instead of exception (#228) --- CHANGELOG.md | 1 + .../Implementation/MainTransformer.php | 14 +++++++++----- src/ObjectCache/ObjectCache.php | 8 ++++---- .../AbstractObjectCacheSentinel.php} | 9 ++------- .../CachedTargetObjectNotFoundSentinel.php | 16 ++++++++++++++++ tests/src/UnitTest/Model/ObjectCacheTest.php | 7 ++++--- 6 files changed, 36 insertions(+), 19 deletions(-) rename src/ObjectCache/{Exception/CachedTargetObjectNotFoundException.php => Sentinel/AbstractObjectCacheSentinel.php} (57%) create mode 100644 src/ObjectCache/Sentinel/CachedTargetObjectNotFoundSentinel.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a49831f..b6a10931 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * perf: `Context` optimization * perf: `ObjectToObjectTransformer` optimization * perf: move `TypeResolver` outside of the hot path +* perf(`ObjectCache`): use sentinel value instead of exception ## 1.10.0 diff --git a/src/MainTransformer/Implementation/MainTransformer.php b/src/MainTransformer/Implementation/MainTransformer.php index 397f3bce..d76f6314 100644 --- a/src/MainTransformer/Implementation/MainTransformer.php +++ b/src/MainTransformer/Implementation/MainTransformer.php @@ -24,10 +24,10 @@ use Rekalogika\Mapper\MainTransformer\MainTransformerInterface; use Rekalogika\Mapper\MainTransformer\Model\DebugContext; use Rekalogika\Mapper\MainTransformer\Model\Path; -use Rekalogika\Mapper\ObjectCache\Exception\CachedTargetObjectNotFoundException; use Rekalogika\Mapper\ObjectCache\Exception\CircularReferenceException as ObjectCacheCircularReferenceException; use Rekalogika\Mapper\ObjectCache\ObjectCache; use Rekalogika\Mapper\ObjectCache\ObjectCacheFactoryInterface; +use Rekalogika\Mapper\ObjectCache\Sentinel\CachedTargetObjectNotFoundSentinel; use Rekalogika\Mapper\Transformer\Exception\RefuseToTransformException; use Rekalogika\Mapper\Transformer\MainTransformerAwareInterface; use Rekalogika\Mapper\Transformer\MixedType; @@ -188,11 +188,8 @@ public function transform( if ($targetTypeForTransformer !== null) { try { - return $objectCache + $result = $objectCache ->getTarget($source, $targetTypeForTransformer); - } catch (CachedTargetObjectNotFoundException) { - $objectCache - ->preCache($source, $targetTypeForTransformer); } catch (ObjectCacheCircularReferenceException $e) { throw new CircularReferenceException( source: $source, @@ -201,6 +198,13 @@ public function transform( previous: $e, ); } + + if (!$result instanceof CachedTargetObjectNotFoundSentinel) { + return $result; + } + + $objectCache + ->preCache($source, $targetTypeForTransformer); } // get and prepare transformer diff --git a/src/ObjectCache/ObjectCache.php b/src/ObjectCache/ObjectCache.php index a5b7fa03..72ca6fd6 100644 --- a/src/ObjectCache/ObjectCache.php +++ b/src/ObjectCache/ObjectCache.php @@ -14,8 +14,8 @@ namespace Rekalogika\Mapper\ObjectCache; use Rekalogika\Mapper\Exception\LogicException; -use Rekalogika\Mapper\ObjectCache\Exception\CachedTargetObjectNotFoundException; use Rekalogika\Mapper\ObjectCache\Exception\CircularReferenceException; +use Rekalogika\Mapper\ObjectCache\Sentinel\CachedTargetObjectNotFoundSentinel; use Rekalogika\Mapper\TypeResolver\TypeResolverInterface; use Symfony\Component\PropertyInfo\Type; @@ -108,7 +108,7 @@ public function containsTarget(mixed $source, Type $targetType): bool public function getTarget(mixed $source, Type $targetType): mixed { if (!\is_object($source)) { - throw new CachedTargetObjectNotFoundException(); + return new CachedTargetObjectNotFoundSentinel(); } $targetTypeString = $this->typeResolver->getTypeString($targetType); @@ -120,12 +120,12 @@ public function getTarget(mixed $source, Type $targetType): mixed } if ($this->isExcluded($source)) { - throw new CachedTargetObjectNotFoundException(); + return new CachedTargetObjectNotFoundSentinel(); } /** @var object */ return $this->cache[$source][$targetTypeString] - ?? throw new CachedTargetObjectNotFoundException(); + ?? new CachedTargetObjectNotFoundSentinel(); } public function saveTarget( diff --git a/src/ObjectCache/Exception/CachedTargetObjectNotFoundException.php b/src/ObjectCache/Sentinel/AbstractObjectCacheSentinel.php similarity index 57% rename from src/ObjectCache/Exception/CachedTargetObjectNotFoundException.php rename to src/ObjectCache/Sentinel/AbstractObjectCacheSentinel.php index 2c2e79a5..d823c9af 100644 --- a/src/ObjectCache/Exception/CachedTargetObjectNotFoundException.php +++ b/src/ObjectCache/Sentinel/AbstractObjectCacheSentinel.php @@ -11,11 +11,6 @@ * that was distributed with this source code. */ -namespace Rekalogika\Mapper\ObjectCache\Exception; +namespace Rekalogika\Mapper\ObjectCache\Sentinel; -use Rekalogika\Mapper\Exception\RuntimeException; - -class CachedTargetObjectNotFoundException extends RuntimeException -{ - public function __construct() {} -} +abstract class AbstractObjectCacheSentinel {} diff --git a/src/ObjectCache/Sentinel/CachedTargetObjectNotFoundSentinel.php b/src/ObjectCache/Sentinel/CachedTargetObjectNotFoundSentinel.php new file mode 100644 index 00000000..e8165bf9 --- /dev/null +++ b/src/ObjectCache/Sentinel/CachedTargetObjectNotFoundSentinel.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\ObjectCache\Sentinel; + +final class CachedTargetObjectNotFoundSentinel extends AbstractObjectCacheSentinel {} diff --git a/tests/src/UnitTest/Model/ObjectCacheTest.php b/tests/src/UnitTest/Model/ObjectCacheTest.php index c385e5c2..293b5d0b 100644 --- a/tests/src/UnitTest/Model/ObjectCacheTest.php +++ b/tests/src/UnitTest/Model/ObjectCacheTest.php @@ -15,8 +15,8 @@ use PHPUnit\Framework\TestCase; use Rekalogika\Mapper\Context\Context; -use Rekalogika\Mapper\ObjectCache\Exception\CachedTargetObjectNotFoundException; use Rekalogika\Mapper\ObjectCache\ObjectCache; +use Rekalogika\Mapper\ObjectCache\Sentinel\CachedTargetObjectNotFoundSentinel; use Rekalogika\Mapper\TypeResolver\Implementation\TypeResolver; use Rekalogika\Mapper\Util\TypeFactory; @@ -37,7 +37,8 @@ public function testObjectCache(): void $this->assertTrue($objectCache->containsTarget($source, TypeFactory::int())); $this->assertSame($target, $objectCache->getTarget($source, TypeFactory::int())); - $this->expectException(CachedTargetObjectNotFoundException::class); - $objectCache->getTarget($source, TypeFactory::float()); + $result = $objectCache->getTarget($source, TypeFactory::float()); + + $this->assertInstanceOf(CachedTargetObjectNotFoundSentinel::class, $result); } }