Welcome Guest, Not a member yet? Register   Sign In
Caching and headers
#71

[eluser]Arjen van Bochoven[/eluser]
I had the code already running on a live site, I need it to cache a rss feed.

I took the liberty to restructure the wiki page, I added some headings and a short summary at the top.

I can confirm that the extension also works in CI 1.6.3, before that, the file-mode constants that the Output Class is using were not there. It would be easy to change those, but I want the code to be as compatible as possible.

Arjen
#72

[eluser]narkaT[/eluser]
Nice idea Smile

I have a small suggestion to reduce the code-redundancy with the CI-core and reduce overhead.
we can determinate if a file is expired without first run unserialze:

Code:
class MY_Output extends CI_Output {

    /**
     * Write a Cache File
     *
     * @access    public
     * @return    void
     */    
    function _write_cache($output)
    {
        parent::_write_cache( serialize(array('headers' => $this->headers, 'output' => $output)) );
    }

    /**
     * Update/serve a cached file
     *
     * @access    public
     * @return    void
     */    
    function _display_cache(&$CFG, &$URI)
    {
        $cache_path = ($CFG->item('cache_path') == '') ? BASEPATH.'cache/' : $CFG->item('cache_path');
            
        if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
        {
            return FALSE;
        }
        
        // Build the file path.  The file name is an MD5 hash of the full URI
        $uri =    $CFG->item('base_url').
                $CFG->item('index_page').
                $URI->uri_string;
                
        $filepath = $cache_path.md5($uri);
        
        if ( ! @file_exists($filepath))
        {
            return FALSE;
        }
    
        if ( ! $fp = @fopen($filepath, FOPEN_READ))
        {
            return FALSE;
        }
            
        flock($fp, LOCK_SH);
        
        $cache = '';
        if (filesize($filepath) > 0)
        {
            $cache = fread($fp, filesize($filepath));
        }
    
        flock($fp, LOCK_UN);
        fclose($fp);
                    
        // Strip out the embedded timestamp        
        if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
        {
            return FALSE;
        }
        
        // Has the file expired? If so we'll delete it.
        if (time() >= trim(str_replace('TS--->', '', $match['1'])))
        {        
            @unlink($filepath);
            log_message('debug', "Cache file has expired. File deleted");
            return FALSE;
        }

        // Display the cache
        $cache = unserialize(str_replace($match['0'], '', $cache));
        $this->headers = $cache['headers'];
        $this->_display($cache['output']);
        log_message('debug', "Cache file is current. Sending it to browser.");        
        return TRUE;
    }
}

I've tested the code with some gziped js/css and images fetched from a DB Wink
#73

[eluser]Arjen van Bochoven[/eluser]
[quote author="narkaT" date="1226503542"]

I have a small suggestion to reduce the code-redundancy with the CI-core and reduce overhead.
we can determinate if a file is expired without first run unserialze:[/quote]

Good suggestion, I like the code-redundancy part!

I still assume this extension stands a better chance of making it into the core when it is fully written out. What do you think?

As for the expiration time: I was happy to get rid of the preg_match() and trade it for unserialize() which I assume is faster and less memory consuming than the regex engine. Maybe someone can confirm this?

cheers,

Arjen
#74

[eluser]Aquillyne[/eluser]
I would certainly imagine so!

I'm glad this is finally coming along.
#75

[eluser]narkaT[/eluser]
[quote author="Arjen van Bochoven" date="1226507284"]As for the expiration time: I was happy to get rid of the preg_match() and trade it for unserialize() which I assume is faster and less memory consuming than the regex engine. Maybe someone can confirm this?[/quote]

okay I've done some (basic) benchmarking and you're right Wink
I've expected the regexp to be faster than the unserialize operation
but it's the other way round.

the code in the wiki takes about ~0.00018 seconds to display the cached
content "my" code takes ~0.00026.

on caching the wiki-code is still faster, but the difference is not that big ~0.00027 to ~0.00029s.


whats more important? speed or less code-redundancy :-S

EDIT:

I've done some further benchmarking for the ones wich are intrested.

the regexp part for stripping out the timestamp IS faster than unserializing the cache file.
but because we have to unserialze the cached data either way... Smile
the "advantage" of the regexp-variant would be the faster detection of expired cache-files.
#76

[eluser]Arjen van Bochoven[/eluser]
Thanks for testing this!

As I said, I am hoping this extension will make it into the core, so as much as I like your solution, I want to leave the code "as is" until we hear back from a CI dev.

-Derek?
#77

[eluser]narkaT[/eluser]
[quote author="Arjen van Bochoven" date="1226507284"]I still assume this extension stands a better chance of making it into the core when it is fully written out. What do you think?[/quote]

I completely agree with you.
as soon as I'm beginning to benchmark things I forget everything else Wink
#78

[eluser]Aquillyne[/eluser]
The code on the wiki is currently the serialize() code. Was my older version better? I don't know how intensive the serialize operation is.

Please add this functionality - I don't care how - into the core.
#79

[eluser]narkaT[/eluser]
did anyone create a thread in the feature request section for this? Wink

It's more likely we get some sort of response in there.
#80

[eluser]Derek Allard[/eluser]
[quote author="Arjen van Bochoven" date="1226517721"]As I said, I am hoping this extension will make it into the core, so as much as I like your solution, I want to leave the code "as is" until we hear back from a CI dev.

-Derek?[/quote]
Yes, this is something we'd want to add to core - great idea, and great work guys!

I'm sorry that I haven't been more active... I'm swamped, and as you can imagine getting pulled in a hundred different directions Wink

I'll make efforts to take a look more closely at what you all have done. On quick inspection let me say that a serialized array may be an approach you want to re-consider. If output got large, PHP could blow up in our faces serializing arrays with that data..




Theme © iAndrew 2016 - Forum software by © MyBB