-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Try to use the APCIterator to clear the APC cache #24008
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
Conversation
when |
return apcu_delete($keysToDelete); | ||
} | ||
|
||
return apcu_clear_cache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be great if this return could be first, so that we can remove one level of indentation above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Added a case for APCIterator, will need some testing though. |
$keysToDelete = new \APCIterator('user', sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY); | ||
} else { | ||
$keysToDelete = array(); | ||
$cacheInfo = apcu_cache_info(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given that apcu_cache_info
exists since v4, but APCIterator
since v3.1.1, I think we just don't need this "else" case (and consider APCIterator in the "else" instead, without any "if")
@@ -71,9 +71,26 @@ protected function doHave($id) | |||
*/ | |||
protected function doClear($namespace) | |||
{ | |||
return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== PHP_SAPI || ini_get('apc.enable_cli')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should just remove the false
from the class_exists
check, to allow using the polyfill implementation of APCuIterator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The polyfill doesn't use autoload to declare the class, so false or true wouldn't change anything.
Which means installing the polyfill is another way to fix this issue immediately yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #24011
On tomorrow, I will try this change : https://github.com/guillaumelecerf/symfony/commit/434fdba469340728b696778fd9bb89db99ea1229 |
This has the side effect to fix a bug resulting in a non-working APC cache: When the app initializes one APC cache, it tries to retrieve its namespace flag key. If the app can't retrieve its flag key, it clears its namespaced cache and adds its flag key back. But when APCuIterator is not usable, the app flushes the whole cache each time, preventing the others APC caches to retrieve their flag key, resulting in a regular full APC cache flush.
Follow up here : #24011 |
…CuIterator everywhere (guillaumelecerf) This PR was merged into the 3.3 branch. Discussion ---------- [Cache] Always require symfony/polyfill-apcu to provide APCuIterator everywhere | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | License | MIT **TL;DR: when APCuIterator is not available (i.e. PHP 5.6 + APCu 4.0.7), the APC cache handling is broken.** When [the app initializes](https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml#L31) one of [the APC caches](https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml#L14-L28), it tries to [retrieve its namespace flag key](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/ApcuTrait.php#L42). If it can't, [it clears its namespaced cache](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/ApcuTrait.php#L43) and [adds its flag key back](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/ApcuTrait.php#L44). But [when APCuIterator is not usable](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/ApcuTrait.php#L74), **the app [flushes the whole cache each time](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/ApcuTrait.php#L76)**, preventing all the APC caches to retrieve their own flag key, resulting in a **perpetual full APC cache flush**. TODO: - [x] add test => https://travis-ci.org/symfony/symfony/jobs/269383629#L3334 See #24008 Commits ------- 9d44442 Always require symfony/polyfill-apcu to provide APCuIterator everywhere
Follow up here : #24011
TL;DR: when APCuIterator is not available (i.e. PHP 5.6 + APCu 4.0.7), the APC cache handling is broken.
When the app initializes one APC cache, it tries to retrieve its namespace flag key.
If the app can't retrieve its flag key, it clears its namespaced cache and adds its flag key back.
But when APCuIterator is not usable, the app flushes the whole cache each time, preventing the others APC caches to retrieve their flag key, resulting in a regular full APC cache flush.
Deeper explanation:
During the cache warmup,
\Symfony\Component\Cache\Adapter\AbstractAdapter::createSystemCache()
is called multiple times with different namespaces, i.e:but when the APCuIterator is not usable, AbstractAdapter does init the APC cache with this code:
Here is the callstack:
Resulting in a complete cache reset between the 2 calls, making every subsequent call to
apcu_exists($version.'@'.$namespace)
false, and so making the whole APC cache completely useless.