Skip to content

Commit

Permalink
minor #30525 [PropertyInfo] Use a single cache item per method (devia…
Browse files Browse the repository at this point in the history
…ntintegral)

This PR was merged into the 4.3-dev branch.

Discussion
----------

[PropertyInfo] Use a single cache item per method

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

Replaces #30523 with a rebase to master.

This PR changes how property metadata is cached, significantly reducing the number of calls made between PHP and the backend cache. Instead of storing one cache item per method and set of arguments, a single cache item is stored per method. This matches well with real-world use, where most properties in an object will need to be inspected.

Note that the absolute numbers in the above PR are best case. In production environments where memcache is on a remote server, we were seeing multiple seconds consumed by memcache calls.

Commits
-------

2a4f8a1 [PropertyInfo] Use a single cache item per method
  • Loading branch information
fabpot committed Apr 3, 2019
2 parents 8da7686 + 2a4f8a1 commit 248aff5
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php
Expand Up @@ -24,6 +24,13 @@ class PropertyInfoCacheExtractor implements PropertyInfoExtractorInterface, Prop
{
private $propertyInfoExtractor;
private $cacheItemPool;

/**
* A cache of property information, first keyed by the method called and
* then by the serialized method arguments.
*
* @var array
*/
private $arrayCache = [];

public function __construct(PropertyInfoExtractorInterface $propertyInfoExtractor, CacheItemPoolInterface $cacheItemPool)
Expand Down Expand Up @@ -103,22 +110,34 @@ private function extract(string $method, array $arguments)
}

// Calling rawurlencode escapes special characters not allowed in PSR-6's keys
$key = rawurlencode($method.'.'.$serializedArguments);

if (\array_key_exists($key, $this->arrayCache)) {
return $this->arrayCache[$key];
$encodedMethod = \rawurlencode($method);
if (\array_key_exists($encodedMethod, $this->arrayCache) && \array_key_exists($serializedArguments, $this->arrayCache[$encodedMethod])) {
return $this->arrayCache[$encodedMethod][$serializedArguments];
}

$item = $this->cacheItemPool->getItem($key);
$item = $this->cacheItemPool->getItem($encodedMethod);

$data = $item->get();
if ($item->isHit()) {
return $this->arrayCache[$key] = $item->get();
$this->arrayCache[$encodedMethod] = $data[$encodedMethod];
// Only match if the specific arguments have been cached.
if (\array_key_exists($serializedArguments, $data[$encodedMethod])) {
return $this->arrayCache[$encodedMethod][$serializedArguments];
}
}

// It's possible that the method has been called, but with different
// arguments, in which case $data will already be initialized.
if (!$data) {
$data = [];
}

$value = $this->propertyInfoExtractor->{$method}(...$arguments);
$item->set($value);
$data[$encodedMethod][$serializedArguments] = $value;
$this->arrayCache[$encodedMethod][$serializedArguments] = $value;
$item->set($data);
$this->cacheItemPool->save($item);

return $this->arrayCache[$key] = $value;
return $this->arrayCache[$encodedMethod][$serializedArguments];
}
}

0 comments on commit 248aff5

Please sign in to comment.