Skip to content

Commit

Permalink
perf(ObjectCache): use sentinel value instead of exception (#228)
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi authored Oct 12, 2024
1 parent bf46668 commit feed0d4
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 9 additions & 5 deletions src/MainTransformer/Implementation/MainTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -201,6 +198,13 @@ public function transform(
previous: $e,
);
}

if (!$result instanceof CachedTargetObjectNotFoundSentinel) {
return $result;
}

$objectCache
->preCache($source, $targetTypeForTransformer);
}

// get and prepare transformer
Expand Down
8 changes: 4 additions & 4 deletions src/ObjectCache/ObjectCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
16 changes: 16 additions & 0 deletions src/ObjectCache/Sentinel/CachedTargetObjectNotFoundSentinel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* 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 {}
7 changes: 4 additions & 3 deletions tests/src/UnitTest/Model/ObjectCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
}

0 comments on commit feed0d4

Please sign in to comment.