Skip to content
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

Slow performance having huge amount of cache files #6087

Closed
sb-relaxt-at opened this issue Sep 26, 2016 · 12 comments

Comments

Projects
None yet
5 participants
@sb-relaxt-at
Copy link
Contributor

commented Sep 26, 2016

We have recently updated a SilverStripe 3.1 based website to 3.4 and are encountering occassional bad loading performance (1-3 seconds versus 200-400ms). It turns out that the longer loading time is caused by a cache cleaning. A cache clean is trigger with a 10% probability in Zend's Core#save. This method is called on any page request, when data regarding the translations are saved. As we do have a large number of image files scaled by GD (some thousands), cleaning a Zend File cache is very slow, as it needs to iterate the thousands of cache files. We had encountered a similar issue in the backend when using a SS_Cache for caching some data increased the loading time mystically.

I am aware that updating/replacing the Zend dependency is discussed, but it would be great to find a solution in the meantime. There might be different options to deal with it:

  • Separate the different caches to own subdirectories. This reduces the number of files that need to be checked when cleaning a specific cache (doesn't resolve the issue when flushing or when accessing the GD cache)
  • Remove no longer needed GD cache files. Judging from the code, there might be cache files without a meaningful content if all transformations have been successful (doesn't improve the situation if transformations have failed)
  • Creating an improved storage backend for Zend ;)

We haven chosen the first option and configured the GDBackend_Manipulations cache backend to use a custom subfolder, which greatly improves loading time of frontend pages with already scaled images.

Furthermore there are some caches (i18n, SS_Configuration, GDBackend_Manipulations) that have a lifetime of null specified, which means infinite validity. I guess that there is no need for those caches to be automatically cleaned (using CLEANING_MODE_OLD). Specifying automatic_cleaning_factor as 0 in the frontend options should prevent these unnecessary calls at all.

@dhensby

This comment has been minimized.

Copy link
Member

commented Sep 26, 2016

Your first option sounds sensible to me, can you show us your implementation, perhaps PR if you think it's suitable?

@kinglozzer

This comment has been minimized.

Copy link
Member

commented Sep 26, 2016

Regarding GD caches - the files should be removed if all the manipulations were successful, so that’s a bug worth fixing. It should be fairly easy to adjust this code to call $this->cache->remove($this->cacheKey) if the cache is empty.

@sb-relaxt-at

This comment has been minimized.

Copy link
Contributor Author

commented Sep 26, 2016

Removing the GD cache file should be indeed very easy, at the mentioned position:

if(empty($cacheData)){
    $this->cache->remove($this->cacheKey);
}else {
    $this->cache->save(serialize($cacheData), $this->cacheKey);
}

Concerning the subdirectories: We are currently configuring different file cache backends for each cache where the cache_dir is set to a dedicated subdirectory. I guess for a PR, a more generic solution solution that plays along with SS_Cache::add_backend and SS_Cache::pick_backend needs to be found.

@sunnysideup

This comment has been minimized.

Copy link
Contributor

commented Dec 8, 2016

Check out this code:

image

What is really weird about that is that it checks if a method exists (isAutomaticCleaningAvailable). The actual method returns false, but who cares ... it goes ahead anyway

@sunnysideup

This comment has been minimized.

Copy link
Contributor

commented Dec 8, 2016

Check this out...:
https://github.com/silverstripe/silverstripe-framework/blob/master/thirdparty/Zend/Cache/Core.php#L369-L380

The method isAutomaticCleaningAvailable can return TRUE or FALSE - who cares ;-)

It exists for every back-end type:

image

Do I see this right or have I been staring at this too much ;-)))?

@sb-relaxt-at

This comment has been minimized.

Copy link
Contributor Author

commented Dec 8, 2016

Yeah this is rather strange... Obviously the new way to determine if auto cleanup is available is by the backend extending Zend_Cache_Backend_ExtendedInterface. If it the chosen backend extends this class, it is assumed to support automatic cleanup.

@kinglozzer

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

Yes, that code looks pretty poorly written by Zend. But caches that don’t support automatic cleaning won’t attempt it regardless of the outcome there, as they don’t support the Zend_Cache::CLEANING_MODE_OLD mode.

@dhensby

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

I assume that $this->_backend->clean($mode); checks isAutomaticCleaningAvailable if $mode == Zend_Cache::CLEANING_MODE_OLD..

@kinglozzer

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

@dhensby It just silently “fails” in the backend driver itself if it’s not supported, for example: https://github.com/silverstripe/silverstripe-framework/blob/3.5/thirdparty/Zend/Cache/Backend/Apc.php#L151-L153

@dhensby

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

strange

@chillu

This comment has been minimized.

Copy link
Member

commented Feb 16, 2017

Note that we're discussing replacing zend_cache for 4.x: #6252

@chillu

This comment has been minimized.

Copy link
Member

commented Mar 7, 2017

We've "fixed" this by using symfony/cache in 4.0, which doesn't support this randomised automatic pruning (see #6678). So the behaviour becomes more predictable, but also means you build up cache files over time - which we're planning to address until 4.0.0. We'll likely default to the same randomised automatic pruning, but give users an option to clean via a cron job in the background instead.

On 3.x, for high volume installations (high concurrency, large volumes of data and caches), I'd recommend a cache driver which can deal with cache pruning itself - relying on filesystem for this is inherently slow.

I'm going to close this issue, but happy to review a 3.x pull request that doesn't break/change APIs. or maybe just a clarification in the docs on where the default cache drivers are appropriate?

@chillu chillu closed this Mar 7, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.