minor #24228 [Serializer] Add local cache to normalizers (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[Serializer] Add local cache to normalizers

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #24206
| License       | MIT
| Doc PR        | -

Should help making the Serializer a bit faster.

Commits
-------

b0c5cf0 [Serializer] Add local cache to normalizers
This commit is contained in:
Nicolas Grekas 2017-09-20 07:22:30 +02:00
commit aad62c427c
8 changed files with 43 additions and 51 deletions

View File

@ -36,6 +36,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
private $propertyTypeExtractor; private $propertyTypeExtractor;
private $attributesCache = array(); private $attributesCache = array();
private $cache = array();
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null) public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null)
{ {
@ -49,7 +50,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
*/ */
public function supportsNormalization($data, $format = null) public function supportsNormalization($data, $format = null)
{ {
return is_object($data) && !$data instanceof \Traversable; return \is_object($data) && !$data instanceof \Traversable;
} }
/** /**
@ -163,7 +164,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
*/ */
public function supportsDenormalization($data, $type, $format = null) public function supportsDenormalization($data, $type, $format = null)
{ {
return class_exists($type); return isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = class_exists($type);
} }
/** /**

View File

@ -66,7 +66,7 @@ class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterfa
*/ */
public function supportsDenormalization($data, $type, $format = null/*, array $context = array()*/) public function supportsDenormalization($data, $type, $format = null/*, array $context = array()*/)
{ {
$context = func_num_args() > 3 ? func_get_arg(3) : array(); $context = \func_num_args() > 3 ? func_get_arg(3) : array();
return '[]' === substr($type, -2) return '[]' === substr($type, -2)
&& $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); && $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context);

View File

@ -19,6 +19,8 @@ use Symfony\Component\Serializer\SerializerAwareTrait;
*/ */
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{ {
private $cache = array();
use SerializerAwareTrait; use SerializerAwareTrait;
/** /**
@ -64,10 +66,14 @@ class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, Se
*/ */
public function supportsDenormalization($data, $type, $format = null) public function supportsDenormalization($data, $type, $format = null)
{ {
if (!class_exists($type)) { if (isset($this->cache[$type])) {
return false; return $this->cache[$type];
} }
return is_subclass_of($type, 'Symfony\Component\Serializer\Normalizer\DenormalizableInterface'); if (!class_exists($type)) {
return $this->cache[$type] = false;
}
return $this->cache[$type] = is_subclass_of($type, 'Symfony\Component\Serializer\Normalizer\DenormalizableInterface');
} }
} }

View File

@ -25,6 +25,12 @@ use Symfony\Component\Serializer\Exception\UnexpectedValueException;
*/ */
class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface
{ {
private static $supportedTypes = array(
\SplFileInfo::class => true,
\SplFileObject::class => true,
File::class => true,
);
/** /**
* @var MimeTypeGuesserInterface * @var MimeTypeGuesserInterface
*/ */
@ -107,13 +113,7 @@ class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface
*/ */
public function supportsDenormalization($data, $type, $format = null) public function supportsDenormalization($data, $type, $format = null)
{ {
$supportedTypes = array( return isset(self::$supportedTypes[$type]);
\SplFileInfo::class => true,
\SplFileObject::class => true,
'Symfony\Component\HttpFoundation\File\File' => true,
);
return isset($supportedTypes[$type]);
} }
/** /**

View File

@ -31,6 +31,12 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
private $format; private $format;
private $timezone; private $timezone;
private static $supportedTypes = array(
\DateTimeInterface::class => true,
\DateTimeImmutable::class => true,
\DateTime::class => true,
);
/** /**
* @param string $format * @param string $format
* @param \DateTimeZone|null $timezone * @param \DateTimeZone|null $timezone
@ -115,13 +121,7 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
*/ */
public function supportsDenormalization($data, $type, $format = null) public function supportsDenormalization($data, $type, $format = null)
{ {
$supportedTypes = array( return isset(self::$supportedTypes[$type]);
\DateTimeInterface::class => true,
\DateTimeImmutable::class => true,
\DateTime::class => true,
);
return isset($supportedTypes[$type]);
} }
/** /**

View File

@ -35,13 +35,14 @@ namespace Symfony\Component\Serializer\Normalizer;
class GetSetMethodNormalizer extends AbstractObjectNormalizer class GetSetMethodNormalizer extends AbstractObjectNormalizer
{ {
private static $setterAccessibleCache = array(); private static $setterAccessibleCache = array();
private $cache = array();
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function supportsNormalization($data, $format = null) public function supportsNormalization($data, $format = null)
{ {
return parent::supportsNormalization($data, $format) && $this->supports(get_class($data)); return parent::supportsNormalization($data, $format) && (isset($this->cache[$type = \get_class($data)]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type));
} }
/** /**
@ -49,7 +50,7 @@ class GetSetMethodNormalizer extends AbstractObjectNormalizer
*/ */
public function supportsDenormalization($data, $type, $format = null) public function supportsDenormalization($data, $type, $format = null)
{ {
return parent::supportsDenormalization($data, $type, $format) && $this->supports($type); return parent::supportsDenormalization($data, $type, $format) && (isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type));
} }
/** /**

View File

@ -30,12 +30,14 @@ namespace Symfony\Component\Serializer\Normalizer;
*/ */
class PropertyNormalizer extends AbstractObjectNormalizer class PropertyNormalizer extends AbstractObjectNormalizer
{ {
private $cache = array();
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function supportsNormalization($data, $format = null) public function supportsNormalization($data, $format = null)
{ {
return parent::supportsNormalization($data, $format) && $this->supports(get_class($data)); return parent::supportsNormalization($data, $format) && (isset($this->cache[$type = \get_class($data)]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type));
} }
/** /**
@ -43,7 +45,7 @@ class PropertyNormalizer extends AbstractObjectNormalizer
*/ */
public function supportsDenormalization($data, $type, $format = null) public function supportsDenormalization($data, $type, $format = null)
{ {
return parent::supportsDenormalization($data, $type, $format) && $this->supports($type); return parent::supportsDenormalization($data, $type, $format) && (isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type));
} }
/** /**

View File

@ -171,7 +171,15 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
*/ */
public function denormalize($data, $type, $format = null, array $context = array()) public function denormalize($data, $type, $format = null, array $context = array())
{ {
return $this->denormalizeObject($data, $type, $format, $context); if (!$this->normalizers) {
throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
}
if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) {
return $normalizer->denormalize($data, $type, $format, $context);
}
throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $type));
} }
/** /**
@ -269,32 +277,6 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz
return $this->decoder->decode($data, $format, $context); return $this->decoder->decode($data, $format, $context);
} }
/**
* Denormalizes data back into an object of the given class.
*
* @param mixed $data data to restore
* @param string $class the expected class to instantiate
* @param string $format format name, present to give the option to normalizers to act differently based on formats
* @param array $context The context data for this particular denormalization
*
* @return object
*
* @throws LogicException
* @throws UnexpectedValueException
*/
private function denormalizeObject($data, $class, $format, array $context = array())
{
if (!$this->normalizers) {
throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
}
if ($normalizer = $this->getDenormalizer($data, $class, $format, $context)) {
return $normalizer->denormalize($data, $class, $format, $context);
}
throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $class));
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */