Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d7b1a72

Browse files
[Cache] serialize objects using native arrays when possible
1 parent 3ccbec3 commit d7b1a72

37 files changed

+1386
-88
lines changed

.php_cs.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ return PhpCsFixer\Config::create()
2020
->append(array(__FILE__))
2121
->exclude(array(
2222
// directories containing files with content that is autogenerated by `var_export`, which breaks CS in output code
23+
'Symfony/Component/Cache/Tests/PhpMarshaller/Fixtures',
2324
'Symfony/Component/DependencyInjection/Tests/Fixtures',
2425
'Symfony/Component/Routing/Tests/Fixtures/dumper',
2526
// fixture templates

src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<argument /> <!-- namespace -->
4242
<argument>0</argument> <!-- default lifetime -->
4343
<argument>%kernel.cache_dir%/pools</argument>
44+
<argument>true</argument>
4445
<call method="setLogger">
4546
<argument type="service" id="logger" on-invalid="ignore" />
4647
</call>

src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,21 @@ public function get(string $key, callable $callback, float $beta = null)
8787
if (null === $this->values) {
8888
$this->initialize();
8989
}
90-
if (null === $value = $this->values[$key] ?? null) {
90+
if (!isset($this->keys[$key])) {
9191
if ($this->pool instanceof CacheInterface) {
9292
return $this->pool->get($key, $callback, $beta);
9393
}
9494

9595
return $this->doGet($this->pool, $key, $callback, $beta ?? 1.0);
9696
}
97+
$value = $this->values[$this->keys[$key]];
98+
9799
if ('N;' === $value) {
98100
return null;
99101
}
102+
if ($value instanceof \Closure) {
103+
return $value();
104+
}
100105
if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
101106
return unserialize($value);
102107
}
@@ -115,15 +120,22 @@ public function getItem($key)
115120
if (null === $this->values) {
116121
$this->initialize();
117122
}
118-
if (!isset($this->values[$key])) {
123+
if (!isset($this->keys[$key])) {
119124
return $this->pool->getItem($key);
120125
}
121126

122-
$value = $this->values[$key];
127+
$value = $this->values[$this->keys[$key]];
123128
$isHit = true;
124129

125130
if ('N;' === $value) {
126131
$value = null;
132+
} elseif ($value instanceof \Closure) {
133+
try {
134+
$value = $value();
135+
} catch (\Throwable $e) {
136+
$value = null;
137+
$isHit = false;
138+
}
127139
} elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
128140
try {
129141
$value = unserialize($value);
@@ -167,7 +179,7 @@ public function hasItem($key)
167179
$this->initialize();
168180
}
169181

170-
return isset($this->values[$key]) || $this->pool->hasItem($key);
182+
return isset($this->keys[$key]) || $this->pool->hasItem($key);
171183
}
172184

173185
/**
@@ -182,7 +194,7 @@ public function deleteItem($key)
182194
$this->initialize();
183195
}
184196

185-
return !isset($this->values[$key]) && $this->pool->deleteItem($key);
197+
return !isset($this->keys[$key]) && $this->pool->deleteItem($key);
186198
}
187199

188200
/**
@@ -198,7 +210,7 @@ public function deleteItems(array $keys)
198210
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key)));
199211
}
200212

201-
if (isset($this->values[$key])) {
213+
if (isset($this->keys[$key])) {
202214
$deleted = false;
203215
} else {
204216
$fallbackKeys[] = $key;
@@ -224,7 +236,7 @@ public function save(CacheItemInterface $item)
224236
$this->initialize();
225237
}
226238

227-
return !isset($this->values[$item->getKey()]) && $this->pool->save($item);
239+
return !isset($this->keys[$item->getKey()]) && $this->pool->save($item);
228240
}
229241

230242
/**
@@ -236,7 +248,7 @@ public function saveDeferred(CacheItemInterface $item)
236248
$this->initialize();
237249
}
238250

239-
return !isset($this->values[$item->getKey()]) && $this->pool->saveDeferred($item);
251+
return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
240252
}
241253

242254
/**
@@ -253,11 +265,17 @@ private function generateItems(array $keys): \Generator
253265
$fallbackKeys = array();
254266

255267
foreach ($keys as $key) {
256-
if (isset($this->values[$key])) {
257-
$value = $this->values[$key];
268+
if (isset($this->keys[$key])) {
269+
$value = $this->values[$this->keys[$key]];
258270

259271
if ('N;' === $value) {
260272
yield $key => $f($key, null, true);
273+
} elseif ($value instanceof \Closure) {
274+
try {
275+
yield $key => $f($key, $value(), true);
276+
} catch (\Throwable $e) {
277+
yield $key => $f($key, null, false);
278+
}
261279
} elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
262280
try {
263281
yield $key => $f($key, unserialize($value), true);

src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
2020
use PhpFilesTrait;
2121

2222
/**
23+
* @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
24+
* Doing so is encouraged because it fits perfectly OPcache's memory model.
25+
*
2326
* @throws CacheException if OPcache is not enabled
2427
*/
25-
public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null)
28+
public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false)
2629
{
30+
$this->appendOnly = $appendOnly;
2731
self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time();
2832
parent::__construct('', $defaultLifetime);
2933
$this->init($namespace, $directory);
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Marshaller;
13+
14+
/**
15+
* @author Nicolas Grekas <[email protected]>
16+
*
17+
* @internal
18+
*/
19+
class Configurator
20+
{
21+
public static $configurators = array();
22+
23+
public function __construct(Registry $registry, array $properties, $value, array $wakeups)
24+
{
25+
$this->{0} = $registry;
26+
$this->{1} = $properties;
27+
$this->{2} = $value;
28+
$this->{3} = $wakeups;
29+
}
30+
31+
public static function __set_state($state)
32+
{
33+
$objects = Registry::$objects;
34+
Registry::$objects = \array_pop(Registry::$stack);
35+
list(, $properties, $value, $wakeups) = $state;
36+
37+
foreach ($properties as $class => $vars) {
38+
(self::$configurators[$class] ?? self::getConfigurator($class))($vars, $objects);
39+
}
40+
foreach ($wakeups as $i) {
41+
$objects[$i]->__wakeup();
42+
}
43+
44+
return $value;
45+
}
46+
47+
public static function getConfigurator($class)
48+
{
49+
$classReflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class);
50+
51+
if (!$classReflector->isInternal()) {
52+
return self::$configurators[$class] = \Closure::bind(function ($properties, $objects) {
53+
foreach ($properties as $name => $values) {
54+
foreach ($values as $i => $v) {
55+
$objects[$i]->$name = $v;
56+
}
57+
}
58+
}, null, $class);
59+
}
60+
61+
switch ($class) {
62+
case 'ArrayIterator':
63+
case 'ArrayObject':
64+
$constructor = $classReflector->getConstructor();
65+
66+
return self::$configurators[$class] = static function ($properties, $objects) use ($constructor) {
67+
foreach ($properties as $name => $values) {
68+
if ("\0" !== $name) {
69+
foreach ($values as $i => $v) {
70+
$objects[$i]->$name = $v;
71+
}
72+
}
73+
}
74+
foreach ($properties["\0"] as $i => $v) {
75+
$constructor->invokeArgs($objects[$i], $v);
76+
}
77+
};
78+
79+
case 'SplObjectStorage':
80+
return self::$configurators[$class] = static function ($properties, $objects) {
81+
foreach ($properties as $name => $values) {
82+
if ("\0" === $name) {
83+
foreach ($values as $i => $v) {
84+
for ($j = 0; $j < \count($v); ++$j) {
85+
$objects[$i]->attach($v[$j], $v[++$j]);
86+
}
87+
}
88+
continue;
89+
}
90+
foreach ($values as $i => $v) {
91+
$objects[$i]->$name = $v;
92+
}
93+
}
94+
};
95+
}
96+
97+
$propertyReflectors = array();
98+
foreach ($classReflector->getProperties(\ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_PRIVATE) as $propertyReflector) {
99+
if (!$propertyReflector->isStatic()) {
100+
$propertyReflector->setAccessible(true);
101+
$propertyReflectors[$propertyReflector->name] = $propertyReflector;
102+
}
103+
}
104+
105+
return self::$configurators[$class] = static function ($properties, $objects) use ($propertyReflectors) {
106+
foreach ($properties as $name => $values) {
107+
if (isset($propertyReflectors[$name])) {
108+
foreach ($values as $i => $v) {
109+
$propertyReflectors[$name]->setValue($objects[$i], $v);
110+
}
111+
} else {
112+
foreach ($values as $i => $v) {
113+
$objects[$i]->$name = $v;
114+
}
115+
}
116+
}
117+
};
118+
}
119+
}

0 commit comments

Comments
 (0)