View previous topic :: View next topic |
Author |
Message |
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Mon Feb 08, 2010 6:13 pm Post subject: Smarty 3: Memory cache resource (APC) |
|
|
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 |
|
kowach Smarty Rookie
Joined: 26 Jan 2011 Posts: 13
|
Posted: Wed Jan 26, 2011 10:14 pm Post subject: |
|
|
Cool. I have now 66% faster page loading
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 |
|
rodneyrehm Administrator
![](images/avatars/18922434164ec3cfa3e63f8.jpg)
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Wed Jan 26, 2011 10:29 pm Post subject: |
|
|
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 |
|
franek Smarty n00b
Joined: 01 Mar 2011 Posts: 2
|
Posted: Tue Mar 01, 2011 1:03 pm Post subject: Re: Smarty 3: Memory cache resource (APC) |
|
|
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 |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Tue Mar 01, 2011 2:59 pm Post subject: |
|
|
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 |
|
franek Smarty n00b
Joined: 01 Mar 2011 Posts: 2
|
Posted: Tue Mar 01, 2011 5:10 pm Post subject: |
|
|
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 |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Tue Mar 01, 2011 6:10 pm Post subject: |
|
|
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 |
|
Alexander84 Smarty Rookie
Joined: 02 Mar 2011 Posts: 6
|
Posted: Mon Mar 14, 2011 10:45 am Post subject: |
|
|
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 |
|
elpmis Smarty Elite
Joined: 07 Jun 2007 Posts: 321
|
Posted: Wed Mar 30, 2011 7:22 am Post subject: Re: Smarty 3: Memory cache resource (APC) |
|
|
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 |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Wed Mar 30, 2011 2:02 pm Post subject: Re: Smarty 3: Memory cache resource (APC) |
|
|
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 |
|
elpmis Smarty Elite
Joined: 07 Jun 2007 Posts: 321
|
Posted: Thu Mar 31, 2011 2:04 pm Post subject: |
|
|
Thanx for your response, but I'm sorry ... I'm not a coder for real.
My host has apc installed and not memcache so I cant use the posted solutions for memcache. |
|
Back to top |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Thu Mar 31, 2011 3:31 pm Post subject: |
|
|
You will want a PHP coder to take the memcache example and replace the function calls with the APC equivalents. |
|
Back to top |
|
ndorphin Smarty Rookie
Joined: 24 Dec 2009 Posts: 15 Location: Berlin, Germany
|
Posted: Wed Jul 20, 2011 4:34 am Post subject: |
|
|
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 |
|
bluejester Smarty Regular
Joined: 26 Apr 2012 Posts: 55
|
Posted: Mon Jan 13, 2014 1:52 pm Post subject: |
|
|
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 |
|
kowach Smarty Rookie
Joined: 26 Jan 2011 Posts: 13
|
Posted: Thu Feb 13, 2014 7:25 pm Post subject: |
|
|
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 |
|
|