8000 [Serializer] Cache the normalizer to use when possible by dunglas · Pull Request #27049 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Serializer] Cache the normalizer to use when possible #27049

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 29, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[Serializer] Cache the normalizer to use when possible
  • Loading branch information
dunglas authored and nicolas-grekas committed Apr 27, 2018
commit c1e850fe834e01d32bbfab42cc5276b75422bdea
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
abstract class AbstractObjectNormalizer extends AbstractNormalizer
abstract class AbstractObjectNormalizer extends AbstractNormalizer implements NormalizerWithCacheableSupportResultInterface
{
const ENABLE_MAX_DEPTH = 'enable_max_depth';
const DEPTH_KEY_PATTERN = 'depth_%s::%s';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* @author Grégoire Pineau <lyrixx@lyrixx.info>
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ConstraintViolationListNormalizer implements NormalizerInterface
class ConstraintViolationListNormalizer implements NormalizerInterface, NormalizerWithCacheableSupportResultInterface
{
/**
* {@inheritdoc}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, NormalizerWithCacheableSupportResultInterface
{
use ObjectToPopulateTrait;
use SerializerAwareTrait;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface
class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface, NormalizerWithCacheableSupportResultInterface
{
private static $supportedTypes = array(
\SplFileInfo::class => true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* @author Jérôme Parmentier <jerome@prmntr.me>
*/
class DateIntervalNormalizer implements NormalizerInterface, DenormalizerInterface
class DateIntervalNormalizer implements NormalizerInterface, DenormalizerInterface, NormalizerWithCacheableSupportResultInterface
{
const FORMAT_KEY = 'dateinterval_format';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface, NormalizerWithCacheableSupportResultInterface
{
const FORMAT_KEY = 'datetime_format';
const TIMEZONE_KEY = 'datetime_timezone';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*
* @author Fred Cox <mcfedr@gmail.com>
*/
class JsonSerializableNormalizer extends AbstractNormalizer
class JsonSerializableNormalizer extends AbstractNormalizer implements NormalizerWithCacheableSupportResultInterface
{
/**
* {@inheritdoc}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Normalizer;

/**
* "supportsNormalization()" methods of normalizers implementing this interface have a cacheable return.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
interface NormalizerWithCacheableSupportResultInterface
{
}
28 changes: 27 additions & 1 deletion src/Symfony/Component/Serializer/Serializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Normalizer\NormalizerWithCacheableSupportResultInterface;

/**
* Serializer serializes and deserializes data.
Expand Down Expand Up @@ -54,6 +55,8 @@ class Serializer implements SerializerInterface, ContextAwareNormalizerInterface
*/
protected $decoder;

private $normalizerCache = array();

/**
* @var array
*/
Expand Down Expand Up @@ -202,11 +205,34 @@ public function supportsDenormalization($data, $type, $format = null, array $con
*/
private function getNormalizer($data, $format, array $context)
{
$type = \is_object($data) ? 'c-'.\get_class($data) : \gettype($data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make any sense to cache by internal type?
I feel like only classes should allow caching but I might be wrong
if the answer is yes, I'd suggest using the prefix on the gettype side, would be better for performance.

Copy link
Contributor
@bendavies bendavies Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what it's doing is caching the fact that no normalizers supported a primitive, which allows a shortcut to escape testing again.

if (
isset($this->normalizerCache[$type][$format]) ||
(isset($this->normalizerCache[$type]) && \array_key_exists($format, $this->normalizerCache[$type]))
Copy link
Member
@nicolas-grekas nicolas-grekas Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (isset($this->normalizerCache[$type][[$format])) looks enough to me here, provided the case for primitive types is done this way:

  • $this->normalizerCache[$type][$format] = false;
  • return $this->normalizerCache[$type][$format] ?: null;

) {
return $this->normalizerCache[$type][$format];
}

$cacheable = true;
foreach ($this->normalizers as $normalizer) {
if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format, $context)) {
if (!$normalizer instanceof NormalizerInterface) {
continue;
}

$cacheable = $cacheable && $normalizer instanceof NormalizerWithCacheableSupportResultInterface;
if ($normalizer->supportsNormalization($data, $format, $context)) {
if ($cacheable) {
$this->normalizerCache[$type][$format] = $normalizer;
}

return $normalizer;
}
}

if ($cacheable) {
// allow to cache primitive types
$this->normalizerCache[$type][$format] = null;
}
}

/**
Expand Down
0