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

Skip to content

Commit 7ce8c1d

Browse files
[Cache] Improve perf of array-based pools
1 parent 5c338cc commit 7ce8c1d

File tree

4 files changed

+113
-63
lines changed

4 files changed

+113
-63
lines changed

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

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,10 @@ function ($key, $value, $isHit) use ($defaultLifetime) {
5656
*/
5757
public function getItem($key)
5858
{
59-
$isHit = $this->hasItem($key);
60-
try {
61-
if (!$isHit) {
62-
$this->values[$key] = $value = null;
63-
} elseif (!$this->storeSerialized) {
64-
$value = $this->values[$key];
65-
} elseif ('b:0;' === $value = $this->values[$key]) {
66-
$value = false;
67-
} elseif (false === $value = unserialize($value)) {
68-
$this->values[$key] = $value = null;
69-
$isHit = false;
70-
}
71-
} catch (\Exception $e) {
72-
CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e));
59+
if (!$isHit = $this->hasItem($key)) {
7360
$this->values[$key] = $value = null;
74-
$isHit = false;
61+
} else {
62+
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
7563
}
7664
$f = $this->createCacheItem;
7765

@@ -84,7 +72,9 @@ public function getItem($key)
8472
public function getItems(array $keys = array())
8573
{
8674
foreach ($keys as $key) {
87-
CacheItem::validateKey($key);
75+
if (!\is_string($key) || !isset($this->expiries[$key])) {
76+
CacheItem::validateKey($key);
77+
}
8878
}
8979

9080
return $this->generateItems($keys, microtime(true), $this->createCacheItem);
@@ -120,15 +110,8 @@ public function save(CacheItemInterface $item)
120110

121111
return true;
122112
}
123-
if ($this->storeSerialized) {
124-
try {
125-
$value = serialize($value);
126-
} catch (\Exception $e) {
127-
$type = is_object($value) ? get_class($value) : gettype($value);
128-
CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e));
129-
130-
return false;
131-
}
113+
if ($this->storeSerialized && null === $value = $this->freeze($value)) {
114+
return false;
132115
}
133116
if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) {
134117
$expiry = microtime(true) + $item["\0*\0defaultLifetime"];

src/Symfony/Component/Cache/Simple/ArrayCache.php

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,20 @@ public function __construct(int $defaultLifetime = 0, bool $storeSerialized = tr
4545
*/
4646
public function get($key, $default = null)
4747
{
48-
foreach ($this->getMultiple(array($key), $default) as $v) {
49-
return $v;
48+
if (!\is_string($key) || !isset($this->expiries[$key])) {
49+
CacheItem::validateKey($key);
50+
}
51+
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > microtime(true) || !$this->delete($key))) {
52+
$this->values[$key] = null;
53+
54+
return $default;
55+
}
56+
if (!$this->storeSerialized) {
57+
return $this->values[$key];
5058
}
59+
$value = $this->unfreeze($key, $isHit);
60+
61+
return $isHit ? $value : $default;
5162
}
5263

5364
/**
@@ -61,7 +72,9 @@ public function getMultiple($keys, $default = null)
6172
throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys)));
6273
}
6374
foreach ($keys as $key) {
64-
CacheItem::validateKey($key);
75+
if (!\is_string($key) || !isset($this->expiries[$key])) {
76+
CacheItem::validateKey($key);
77+
}
6578
}
6679

6780
return $this->generateItems($keys, microtime(true), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; });
@@ -87,7 +100,9 @@ public function deleteMultiple($keys)
87100
*/
88101
public function set($key, $value, $ttl = null)
89102
{
90-
CacheItem::validateKey($key);
103+
if (!\is_string($key)) {
104+
CacheItem::validateKey($key);
105+
}
91106

92107
return $this->setMultiple(array($key => $value), $ttl);
93108
}
@@ -103,27 +118,20 @@ public function setMultiple($values, $ttl = null)
103118
$valuesArray = array();
104119

105120
foreach ($values as $key => $value) {
106-
\is_int($key) || CacheItem::validateKey($key);
121+
if (!\is_int($key) && !(\is_string($key) && isset($this->expiries[$key]))) {
122+
CacheItem::validateKey($key);
123+
}
107124
$valuesArray[$key] = $value;
108125
}
109126
if (false === $ttl = $this->normalizeTtl($ttl)) {
110127
return $this->deleteMultiple(array_keys($valuesArray));
111128
}
112-
if ($this->storeSerialized) {
113-
foreach ($valuesArray as $key => $value) {
114-
try {
115-
$valuesArray[$key] = serialize($value);
116-
} catch (\Exception $e) {
117-
$type = is_object($value) ? get_class($value) : gettype($value);
118-
CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e));
119-
120-
return false;
121-
}
122-
}
123-
}
124129
$expiry = 0 < $ttl ? microtime(true) + $ttl : PHP_INT_MAX;
125130

126131
foreach ($valuesArray as $key => $value) {
132+
if ($this->storeSerialized && null === $value = $this->freeze($value)) {
133+
return false;
134+
}
127135
$this->values[$key] = $value;
128136
$this->expiries[$key] = $expiry;
129137
}

src/Symfony/Component/Cache/Tests/Adapter/ArrayAdapterTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ public function testGetValuesHitAndMiss()
3636

3737
// Hit
3838
$item = $cache->getItem('foo');
39-
$item->set('4711');
39+
$item->set('::4711');
4040
$cache->save($item);
4141

4242
$fooItem = $cache->getItem('foo');
4343
$this->assertTrue($fooItem->isHit());
44-
$this->assertEquals('4711', $fooItem->get());
44+
$this->assertEquals('::4711', $fooItem->get());
4545

4646
// Miss (should be present as NULL in $values)
4747
$cache->getItem('bar');
@@ -50,7 +50,7 @@ public function testGetValuesHitAndMiss()
5050

5151
$this->assertCount(2, $values);
5252
$this->assertArrayHasKey('foo', $values);
53-
$this->assertSame(serialize('4711'), $values['foo']);
53+
$this->assertSame(serialize('::4711'), $values['foo']);
5454
$this->assertArrayHasKey('bar', $values);
5555
$this->assertNull($values['bar']);
5656
}

src/Symfony/Component/Cache/Traits/ArrayTrait.php

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,34 @@ trait ArrayTrait
3434
*/
3535
public function getValues()
3636
{
37-
return $this->values;
37+
if (!$this->storeSerialized) {
38+
return $this->values;
39+
}
40+
41+
$values = $this->values;
42+
foreach ($values as $k => $v) {
43+
if (null === $v || 'N;' === $v) {
44+
continue;
45+
}
46+
if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
47+
$values[$k] = serialize($v);
48+
}
49+
}
50+
51+
return $values;
3852
}
3953

4054
/**
4155
* {@inheritdoc}
4256
*/
4357
public function hasItem($key)
4458
{
59+
if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
60+
return true;
61+
}
4562
CacheItem::validateKey($key);
4663

47-
return isset($this->expiries[$key]) && ($this->expiries[$key] > microtime(true) || !$this->deleteItem($key));
64+
return isset($this->expiries[$key]) && !$this->deleteItem($key);
4865
}
4966

5067
/**
@@ -62,8 +79,9 @@ public function clear()
6279
*/
6380
public function deleteItem($key)
6481
{
65-
CacheItem::validateKey($key);
66-
82+
if (!\is_string($key) || !isset($this->expiries[$key])) {
83+
CacheItem::validateKey($key);
84+
}
6785
unset($this->values[$key], $this->expiries[$key]);
6886

6987
return true;
@@ -80,21 +98,13 @@ public function reset()
8098
private function generateItems(array $keys, $now, $f)
8199
{
82100
foreach ($keys as $i => $key) {
83-
try {
84-
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
85-
$this->values[$key] = $value = null;
86-
} elseif (!$this->storeSerialized) {
87-
$value = $this->values[$key];
88-
} elseif ('b:0;' === $value = $this->values[$key]) {
89-
$value = false;
90-
} elseif (false === $value = unserialize($value)) {
91-
$this->values[$key] = $value = null;
92-
$isHit = false;
93-
}
94-
} catch (\Exception $e) {
95-
CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e));
101+
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
96102
$this->values[$key] = $value = null;
97-
$isHit = false;
103+
} else {
104+
$value = $this->values[$key];
105+
if ($this->storeSerialized) {
106+
$value = $this->unfreeze($key, $isHit);
107+
}
98108
}
99109
unset($keys[$i]);
100110

@@ -105,4 +115,53 @@ private function generateItems(array $keys, $now, $f)
105115
yield $key => $f($key, null, false);
106116
}
107117
}
118+
119+
private function freeze($value)
120+
{
121+
if (null === $value) {
122+
return 'N;';
123+
}
124+
if (\is_string($value)) {
125+
// Serialize strings if they could be confused with serialized objects or arrays
126+
if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
127+
return serialize($value);
128+
}
129+
} elseif (!\is_scalar($value)) {
130+
try {
131+
$serialized = serialize($value);
132+
} catch (\Exception $e) {
133+
$type = is_object($value) ? get_class($value) : gettype($value);
134+
CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e));
135+
136+
return;
137+
}
138+
// Keep value serialized if it contains any objects or any internal references
139+
if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
140+
return $serialized;
141+
}
142+
}
143+
144+
return $value;
145+
}
146+
147+
private function unfreeze(string $key, bool &$isHit)
148+
{
149+
if ('N;' === $value = $this->values[$key]) {
150+
return null;
151+
}
152+
if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
153+
try {
154+
$value = unserialize($value);
155+
} catch (\Exception $e) {
156+
CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e));
157+
$value = false;
158+
}
159+
if (false === $value) {
160+
$this->values[$key] = $value = null;
161+
$isHit = false;
162+
}
163+
}
164+
165+
return $value;
166+
}
108167
}

0 commit comments

Comments
 (0)