Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Smarty 3: Memory cache resource (APC)
Goto page 1, 2  Next
 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks
View previous topic :: View next topic  
Author Message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Mon Feb 08, 2010 6:13 pm    Post subject: Smarty 3: Memory cache resource (APC) Reply with quote

If you use APC (Alternate PHP Cache) as an op-code cache, you also have a built-in memory storage area for lightning fast access to data. Wouldn't it be nice to store your Smarty cache files here? Look no further.

Drop the plugin into your plugins_dir, then set:

Code:
$smarty->loadCacheResource('apc');
$smarty->setCaching(true);


And now you have your Smarty cache files loaded/saved from memory! Be aware you are limited to the amount of memory allocated by APC. Watch the stats, if the cache gets full (lots of swapping) consider upping the memory allocation or saving smaller/less files.


The plugin source (save as cacheresource.apc.php in your plugins_dir):


Code:
<?php

/**
* Smarty Plugin CacheResource APC
*
* Implements APC resource for the HTML cache
*
* @package Smarty
* @subpackage Cacher
* @author Monte Ohrt
*/

/**
* This class does contain all necessary methods for the HTML cache with APC
*/
class Smarty_CacheResource_APC {
    function __construct($smarty)
    {
        $this->smarty = $smarty;
        // test if APC is present
        if(!function_exists('apc_cache_info'))
          throw new Exception('APC Template Caching Error: APC is not installed');
    }
    /**
    * Returns the filepath of the cached template output
    *
    * @param object $_template current template
    * @return string the cache filepath
    */
    public function getCachedFilepath($_template)
    {
        return md5($_template->getTemplateFilepath().$_template->cache_id.$template->compile_id);
    }

    /**
    * Returns the timpestamp of the cached template output
    *
    * @param object $_template current template
    * @return integer |booelan the template timestamp or false if the file does not exist
    */
    public function getCachedTimestamp($_template)
    {
        apc_fetch($this->getCachedFilepath($_template), $success);
        return $success ? time() : false;
    }

    /**
    * Returns the cached template output
    *
    * @param object $_template current template
    * @return string |booelan the template content or false if the file does not exist
    */
    public function getCachedContents($_template)
    {
        $_cache_content = apc_fetch($this->getCachedFilepath($_template));
        $_smarty_tpl = $_template;
        ob_start();
        eval("?>" . $_cache_content);
        return ob_get_clean();
    }

    /**
    * Writes the rendered template output to cache file
    *
    * @param object $_template current template
    * @return boolean status
    */
    public function writeCachedContent($_template, $content)
    {
        return apc_store($this->getCachedFilepath($_template), $content, $_template->cache_lifetime);
    }

    /**
    * Empty cache folder
    *
    * @param integer $exp_time expiration time
    * @return integer number of cache files deleted
    */
    public function clearAll($exp_time = null)
    {
        return apc_clear_cache('user');
    }
    /**
    * Empty cache for a specific template
    *
    * @param string $resource_name template name
    * @param string $cache_id cache id
    * @param string $compile_id compile id
    * @param integer $exp_time expiration time
    * @return integer number of cache files deleted
    */
    public function clear($resource_name, $cache_id, $compile_id, $exp_time)
    {
        return apc_delete(md5($resource_name.$cache_id.$compile_id));
    }
}

?>
Back to top
View user's profile Send private message Visit poster's website
kowach
Smarty Rookie


Joined: 26 Jan 2011
Posts: 13

PostPosted: Wed Jan 26, 2011 10:14 pm    Post subject: Reply with quote

Cool. I have now 66% faster page loading Smile

And you must set default caching type or it will use file cache.

Code:
$smarty->setCachingType('apc');


Here is some interesting stats with ab -n 50 -c 20 -t 10 http://10.0.0.100/

APC disabled, File cache:
Requests per second: 14.67 [#/sec] (mean)
Time per request: 1362.931 [ms] (mean)

APC enabled, still File cache:
Requests per second: 39.62 [#/sec] (mean)
Time per request: 504.733 [ms] (mean)

APC enabled, APC cache:
Requests per second: 45.50 [#/sec] (mean)
Time per request: 439.565 [ms] (mean)


why APC speeds up PHP loading so much?
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Wed Jan 26, 2011 10:29 pm    Post subject: Reply with quote

kowach wrote:
why APC speeds up PHP loading so much?


Because APC is an in-memory (RAM) storage. RAM is very fast compared to HDD. The HDD is a bottle neck. But beware that you can never have enough RAM. If you shove too much data into it, it will be swapped to disk - and you start the HDD dance all over again - but this time on a worse scale.

We used memcache across our system. 6 web servers dedicate 500MB each, giving us a total of 3GB space for object- and output-caching.

If you'd take 3GB from one machine, even if it has 16GB of RAM available, you're trade off may not be that good. The other systems (apache, mysql, wtf) need RAM too - and if they don't get enough, the perform badly. So you may end up boosting your smarty output cache by throttling performance of other services.

Have a good look at what kind of volume you're shoving down APCs throat. First RAM has limits, second APCs just plain sucks.
Back to top
View user's profile Send private message Visit poster's website
franek
Smarty n00b


Joined: 01 Mar 2011
Posts: 2

PostPosted: Tue Mar 01, 2011 1:03 pm    Post subject: Re: Smarty 3: Memory cache resource (APC) Reply with quote

mohrt wrote:
If you use APC (Alternate PHP Cache) as an op-code cache, you also have a built-in memory storage area for lightning fast access to data. Wouldn't it be nice to store your Smarty cache files here? Look no further.

Drop the plugin into your plugins_dir, then set:

Code:
$smarty->loadCacheResource('apc');
$smarty->setCaching(true);


And now you have your Smarty cache files loaded/saved from memory! Be aware you are limited to the amount of memory allocated by APC. Watch the stats, if the cache gets full (lots of swapping) consider upping the memory allocation or saving smaller/less files.


Hi,

This plugins works fine to save cache files in Apc.
With Smarty2, It was possible to save compiled file too. How can we do it with Smarty3 ?
Any clues would be very appreciate.

The directory compiled_c is growing exponentially.

Thanks,
Fran'
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Tue Mar 01, 2011 2:59 pm    Post subject: Reply with quote

How were you saving compiled files with Smarty 2?

The thing is, compiled files are PHP. If you don't have them on the file system, APC can't cache them and it requires an eval() to run them which is a huge performance expense. You could possibly make a memory-based hard disk and put your compiled files there. That is not something part of Smarty.
Back to top
View user's profile Send private message Visit poster's website
franek
Smarty n00b


Joined: 01 Mar 2011
Posts: 2

PostPosted: Tue Mar 01, 2011 5:10 pm    Post subject: Reply with quote

mohrt wrote:
How were you saving compiled files with Smarty 2?


I don't know how we made that. It is like a spaghetti code but we don't have any compiled files in template_c directory and all templates were saved in APC.

mohrt wrote:

The thing is, compiled files are PHP. If you don't have them on the file system, APC can't cache them and it requires an eval() to run them which is a huge performance expense. You could possibly make a memory-based hard disk and put your compiled files there. That is not something part of Smarty.


Ok. But how can we reduce the size of templates_c directory ? Templates_c directory can become quickly huge ?

Is there a mean to write a plugin for overriding internal write files (Smarty_Internal_Write_Files) ?

Thanks for your answer,
Fran'
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Tue Mar 01, 2011 6:10 pm    Post subject: Reply with quote

The size of the template_c directory will grow in proportion to the number of templates in the template directory. However, you can break up the files in that directory with the use of sub-directory design. You can set that property on Smarty:

http://www.smarty.net/docs/en/variable.use.sub.dirs.tpl

and it will handle it for you.
Back to top
View user's profile Send private message Visit poster's website
Alexander84
Smarty Rookie


Joined: 02 Mar 2011
Posts: 6

PostPosted: Mon Mar 14, 2011 10:45 am    Post subject: Reply with quote

Environment
- Windows
- PHP + APC
- CodeIgniter 2
- Smarty 3.0.7

Your plugin works here, but, unfortunately, outputs notices as follows:
Code:

A PHP Error was encountered Severity: Notice Message: Undefined variable: template Filename: cacheresource.apc.php Line Number: 33

A PHP Error was encountered Severity: Notice Message: Trying to get property of non-object Filename: cacheresource.apc.php Line Number: 33


Any clues how to overcome this trouble, please?

Update
In case it's connected with missing underscore in source code ($template->compile_id) and I put underscore ($_template->compile_id), then another notice comes:
Code:
A PHP Error was encountered Severity: Notice Message: Undefined variable: no_render Filename: cacheresource.apc.php(58) : eval()'d code Line Number: 28


Update 2, the solution
Step 1.
Put underscore.
BEFORE $template->compile_id
AFTER $_template->compile_id

Step 2.
Tweak getCachedContents as follows
Code:

    public function getCachedContents($_template, $no_render = false)
    {
      if (!$no_render) { ob_start(); }
      $_cache_content = apc_fetch($this->getCachedFilepath($_template));
      $_smarty_tpl = $_template;
      eval("?>" . $_cache_content);
      if ($no_render) {   return null; } else { return ob_get_clean(); }
    }
Back to top
View user's profile Send private message
elpmis
Smarty Elite


Joined: 07 Jun 2007
Posts: 321

PostPosted: Wed Mar 30, 2011 7:22 am    Post subject: Re: Smarty 3: Memory cache resource (APC) Reply with quote

mohrt wrote:
If you use APC (Alternate PHP Cache) as an op-code cache, you also have a built-in memory storage area for lightning fast access to data. Wouldn't it be nice to store your Smarty cache files here? Look no further.


How can I use memory caching with Smarty2?
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Wed Mar 30, 2011 2:02 pm    Post subject: Re: Smarty 3: Memory cache resource (APC) Reply with quote

elpmis wrote:
mohrt wrote:
If you use APC (Alternate PHP Cache) as an op-code cache, you also have a built-in memory storage area for lightning fast access to data. Wouldn't it be nice to store your Smarty cache files here? Look no further.


How can I use memory caching with Smarty2?


Search the forums for "memcache", there is info here about it.
Back to top
View user's profile Send private message Visit poster's website
elpmis
Smarty Elite


Joined: 07 Jun 2007
Posts: 321

PostPosted: Thu Mar 31, 2011 2:04 pm    Post subject: Reply with quote

Thanx for your response, but I'm sorry ... I'm not a coder for real.

My host has apc installed and not memcache Sad so I cant use the posted solutions for memcache.
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Thu Mar 31, 2011 3:31 pm    Post subject: Reply with quote

You will want a PHP coder to take the memcache example and replace the function calls with the APC equivalents.
Back to top
View user's profile Send private message Visit poster's website
ndorphin
Smarty Rookie


Joined: 24 Dec 2009
Posts: 15
Location: Berlin, Germany

PostPosted: Wed Jul 20, 2011 4:34 am    Post subject: Reply with quote

I'll notice that if you use apc with apc.cache_by_default = On and without any filter than your smarty cache files should be already in apc opcode cache. You can test it by viewing the opcode cache (take apc.php). In my case using the Smarty_CacheResource_APC class wasn't faster then using the opcode cache, it was 50% slower!!! If you use opcode cache for smarty cache files take care about apc option apc.stat - if set to 0 your cached files will never renewed (you can solve this by deleteing the cache file entry from opcode cache by apc_delete_file() [apc > 3.1.1] if your smarty cached file should be renewed).

ndorphin
Back to top
View user's profile Send private message
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Mon Jan 13, 2014 1:52 pm    Post subject: Reply with quote

Hello,

It looks like this plugin is no longer up-to-date with Smarty 3.1x.
I put the code in a cacheresource.apc.php file in my plugins_dir.

Now when I run :
Code:
$this->Smarty->loadCacheResource('apc');


I have the following SmartyException :
Call of unknown method 'loadCacheResource

Now if I try :
Code:
$this->Smarty   ->  SetCachingType('apc');


I have the following warning :
Warning: Missing argument 1 for Smarty_CacheResource_APC::__construct()

And the following fatal error :
Fatal error: Call to undefined method Smarty_CacheResource_APC::populate()

Now if I try :
Code:
$this->Smarty   ->  SetCachingType('apc');
$this->Smarty   ->  RegisterCacheResource('apc', new \Smarty_CacheResource_APC($this->Smarty));


Here's the error I get :
Catchable fatal error: Argument 2 passed to Smarty_Internal_TemplateBase::registerCacheResource() must be an instance of Smarty_CacheResource, instance of Smarty_CacheResource_APC given

What's wrong with this ?

Thanks,
Ben
Back to top
View user's profile Send private message Visit poster's website
kowach
Smarty Rookie


Joined: 26 Jan 2011
Posts: 13

PostPosted: Thu Feb 13, 2014 7:25 pm    Post subject: Reply with quote

This is enough:

Code:

$smarty->addPluginsDir ( "/path_to_plugins_dir/" );
$smarty->setCachingType ( "apc" );


Plugin for Smarty 3.1.x is much more simplified. Put this file into plugins dir:
Code:
<?php

/**
 * APC CacheResource for Smarty 3.1.x
 *
 * CacheResource Implementation based on the KeyValueStore API to use
 * apc as the storage resource for Smarty's output caching.
 *
 */
class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore {
   
    public function __construct()
    {
        if(!function_exists('apc_cache_info'))
          throw new Exception('APC Template Caching Error: APC is not installed');
    }
    /**
     * Read values for a set of keys from cache
     *
     * @param array $keys list of keys to fetch
     * @return array list of values with the given keys used as indexes
     * @return boolean true on success, false on failure
     */
    protected function read(array $keys)
    {
      return apc_fetch($keys);
    }
    /**
     * Save values for a set of keys to cache
     *
     * @param array $keys list of values to save
     * @param int $expire expiration time
     * @return boolean true on success, false on failure
     */
    protected function write(array $keys, $expire=null)
    {
        return apc_store($keys, null, $expire);
    }
    /**
     * Remove values from cache
     *
     * @param array $keys list of keys to delete
     * @return boolean true on success, false on failure
     */
    protected function delete(array $keys)
    {
        foreach ($keys as $k) {
           apc_delete($k);
        }
        return true;
    }
    /**
     * Remove *all* values from cache
     *
     * @return boolean true on success, false on failure
     */
    protected function purge()
    {
        return apc_clear_cache('user');
    }
}
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP