CSS delivery from cache is inefficient

Affected version
2.2.4

Kirby

Well-known member
If configured and possible, XenForo stores rendered CSS in a cache using the configured provider (Memcached, Redis, etc.) in \XF\CssRenderer::cacheFinalOutput
PHP:
protected function cacheFinalOutput(array $templates, $output)
{
        if (!is_string($output) || !strlen($output))
        {
                return;
        }

        if ($this->allowCached && $this->allowFinalCacheUpdate && $this->cache && $this->includeExtraParams)
        {
                $this->cache->save($this->getFinalCacheKey($templates), $output, 3600);
        }
}

Depending on the provider, the data might be compressed (using Memcached for example, OPT_COMPRESSION is enabled by default).

So when loading the cached rendered CSS, this data will be decompressed when loaded in \XF\CssRenderer::render
PHP:
public function render($templates, $includeExtraParams = true)
{
    [...]

    $output = $this->getFinalCachedOutput($templates);
    if (!$output)
    {
        [...]
    }

    return $output;
}

protected function getFinalCachedOutput(array $templates)
{
        if (!$this->allowCached || !$this->cache || !$this->includeExtraParams)
        {
                return false;
        }

        $key = $this->getFinalCacheKey($templates);
        return $this->cache->fetch($key);
}

The only processing XenForo does afterwards is to add @charset "UTF-8" and two newlines in \XF\CssWriter::run
PHP:
public function run(array $templates, $styleId, $languageId, $validation = null)
{
    [...]

    $output = $this->renderer->render($templates);
    $output = $this->finalizeOutput($output);

    return $this->getResponse($output);
}

public function finalizeOutput($output)
{
    return '@charset "UTF-8";' . "\n\n" . $output;
}

When finally sending the response and the client is capable, XenForo will compress the response with gzip level 1.

This seems inefficient as the data is decompressed and again compressed for every css.php request.

Ideally the data should be stored in cache with maximum compression and delivered to the client without intermediate decompression.
 

Xon

Well-known member
@Kirby I actually do this with my Redis Cache add-on. It is stored to the cache using gzip (even if other compression methods are supported) and this gzip'ed css is then sent to clients which are marked as supporting gzip.
 

Masetrix

Well-known member
@Kirby I actually do this with my Redis Cache add-on. It is stored to the cache using gzip (even if other compression methods are supported) and this gzip'ed css is then sent to clients which are marked as supporting gzip.
That is thats one of the reason why we have set: $config['enableGzip'] = false; in the config.php
 
Top