View previous topic :: View next topic |
Author |
Message |
bzvarik Smarty n00b
Joined: 01 Mar 2011 Posts: 4
|
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Tue Mar 01, 2011 10:02 pm Post subject: Re: Smarty 3 and Memcache |
|
|
bzvarik wrote: | Anyone out there have successfully implemented memcache with Smarty 3? |
Yes. in fact I've implemented a generic interface for key/values stores (such as memcache, APC, …). The solution will be released as part of Smarty 3.1. So you're getting a memcache compatible interface from smarty itself. merry christmas…
Ok, I see you've found it already…
bzvarik wrote: | Now I'm getting PHP Fatal error: Class Smarty_CacheResource_Memcache contains 1 abstract method and must therefore be declared abstract or implement the remaining methods |
Looks to me like you should get the latest revisions of those classes. We've changed the API (again and again) since I wrote them originally… |
|
Back to top |
|
bzvarik Smarty n00b
Joined: 01 Mar 2011 Posts: 4
|
Posted: Wed Mar 02, 2011 12:04 am Post subject: |
|
|
Thanks, i overlooked that there are newer revisions of these sysplugin classes.
So now I have :
smarty_cacheresource.php - rev 4024
smarty_cacheresource_keyvaluestore.php - rev 4011
cacheresource.memcache.php - rev 4015
I believe that these are the most recent versions.
Smarty itself - we are using Smarty 3.0.6 (3.0.7 is most recent stable version now). Should I get Smarty 3.0.7 as well?
Now it seems to be almost working, BUT cacheresource.memcache.php is missing these methods (maybe more, not sure yet)
getCachedTimestamp
getCachedContents
Any idea where I can get complete up-to-date class with these methods a well?
Regarding Smarty 3.1 - will it have implemented also memcache caching itself (kind of out of the box sollution) or what exactly will be available?
Also, do you know when Smarty 3.1 will be released?
And thanks again for your help! |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Wed Mar 02, 2011 1:01 am Post subject: |
|
|
bzvarik wrote: | Now it seems to be almost working, BUT cacheresource.memcache.php is missing these methods (maybe more, not sure yet)
getCachedTimestamp
getCachedContents
Any idea where I can get complete up-to-date class with these methods a well? |
yeah, these methods have been dropped. As I said, the API changed again. Which is exactly why we didn't propagate the branch. Check back some revisions on smarty_cacheresource_keyvaluestore.php. Somewhere those methods should pop up.
bzvarik wrote: | Regarding Smarty 3.1 - will it have implemented also memcache caching itself (kind of out of the box sollution) or what exactly will be available? |
yes and no. all the fancy business will be provided by the core. The actual memcache access is something everyone should implement themselves. Some use Memcache, others Memcached, others can't use a PECL at all, … But you'd get there in minutes by looking at the provided examples.
[quote="bzvarik"]Also, do you know when Smarty 3.1 will be released?
no. we're getting closer, though. |
|
Back to top |
|
bzvarik Smarty n00b
Joined: 01 Mar 2011 Posts: 4
|
Posted: Wed May 04, 2011 8:36 pm Post subject: |
|
|
Hi,
Two months past – do you guys already know something new about release date of Smarty 3.1 which would make memcache caching easier?
Also, I have been able to utilize memcache, everything seems to be working fine now, except getCachedContents.
Here is Smarty_Internal_CacheResource_File::getCachedContents and it works fine with file-based caching:
Code: |
public function getCachedContents($_template, $no_render = false)
{
if (!$no_render) {
ob_start();
}
$_smarty_tpl = $_template;
include $_template->getCachedFilepath();
if ($no_render) {
return null;
} else {
return ob_get_clean();
}
}
|
Mine ''memcache' version of the function which looks pretty much same, except I’m getting data from memcache rather then including file from a filesystem:
Code: |
public function getCachedContents($_template, $no_render = false)
{
if (!$no_render) {
ob_start();
}
$content= $memcache->get( $this->$this->getCacheId($_template));
echo $content;
if ($no_render) {
return null;
} else {
return ob_get_clean();
}
}
|
I’m getting content without any problem, but probably because of the buffering, I’m getting at the very top of the template also PHP code like this (just an example):
Code: | <?php /*%%SmartyHeaderCode:5844581574dc1af22021fa4-12208418%%*/if(!defined('SMARTY_DIR')) exit('no direct access allowed');
$_smarty_tpl->decodeProperties(array (
'file_dependency' =>
array (
'4a6ffbb0594876d710d847f8952e956660bcd955' =>
array (
0 => 'store:store_index.tpl',
1 => 1304538660,
2 => 'store',
),
),
'nocache_hash' => '5844581574dc1af22021fa4-12208418',
'has_nocache_code' => true,
'cache_lifetime' => '60',
)); /*/%%SmartyHeaderCode%%*/?>
<?php if (!$no_render) {?>
|
How should I be outputting content from memcache to make sure buffering will be working fine and this PHP code will not be included on the top of every cached version of the template output? I assume it has something to do with ob_start().
Code: |
include $_template->getCachedFilepath();
|
outputs content immediately, but
Code: |
$content= $memcache->get( $this->$this->getCacheId($_template));
|
just assigns it to variable which has to be outputted later somehow. Not sure if echoing it is the best thing to do.
Thanks for help! |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Wed May 04, 2011 8:50 pm Post subject: |
|
|
bzvarik wrote: | Two months past – do you guys already know something new about release date of Smarty 3.1 which would make memcache caching easier? |
without making any promises: looks like this month. at least we're packing it up…
Code: |
$content= $memcache->get( $this->$this->getCacheId($_template));
echo $content;
|
should be
Code: |
$content= $memcache->get( $this->$this->getCacheId($_template));
eval($content);
|
|
|
Back to top |
|
bzvarik Smarty n00b
Joined: 01 Mar 2011 Posts: 4
|
Posted: Wed May 04, 2011 11:12 pm Post subject: |
|
|
Hm, doesn't really work. Content of $content is actually combination of PHP and HTML.
So it is something like
Code: |
<?php /*%%SmartyHeaderCode:5844581574dc1af22021fa4-12208418%%*/if(!defined('SMARTY_DIR')) exit('no direct access allowed');
$_smarty_tpl->decodeProperties(array (
'file_dependency' =>
array (
'4a6ffbb0594876d710d847f8952e956660bcd955' =>
array (
0 => 'store:store_index.tpl',
1 => 1304538660,
2 => 'store',
),
),
'nocache_hash' => '5844581574dc1af22021fa4-12208418',
'has_nocache_code' => true,
'cache_lifetime' => '60',
)); /*/%%SmartyHeaderCode%%*/?>
<?php if (!$no_render) {?>
<html>
<head>
</head>
<body>
<div>some content here</div>
</body>
</html>
|
Thing is that eval will evaluate string what is passed to function as a PHP code.
eg this works fine:
Code: |
$content = "echo 'test';";
eval($content);
|
But this will cause error:
Code: |
$content = "<?php echo 'test';?><html>some html here</html>";
eval($content);
|
Thanks for helping me with this! |
|
Back to top |
|
rippergun Smarty n00b
Joined: 06 May 2011 Posts: 2
|
Posted: Fri May 06, 2011 7:59 am Post subject: Working solution |
|
|
Hi, we currently use this solution. It's working fine. However performance are bad with the "eval".
Code: |
/**
* 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, $no_render = false)
{
if (!$no_render) {
ob_start();
}
$_smarty_tpl = $_template;
eval("?>" . $this->memcache->get($_template->getCachedFilepath()));
if ($no_render) {
return null;
} else {
return ob_get_clean();
}
return false;
}
|
Note the eval("?>" .
You should close the PHP tag before evaluating the code.
FYI : we trying to find another solution without the eval() |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Fri May 06, 2011 8:03 am Post subject: Re: Working solution |
|
|
rippergun wrote: | FYI : we trying to find another solution without the eval() |
evaluating the cached template is necessary if you're dealing with dynamic (non-caching) sections/functions. Since such a non-caching element can behave whatever way it likes, there is no real way around eval(). |
|
Back to top |
|
emt Smarty Regular
Joined: 10 Dec 2009 Posts: 43
|
Posted: Wed May 25, 2011 10:07 am Post subject: |
|
|
Just wondered, couldn't we get around 'eval' (and get the benefits of the APC OpCode Cache) by combining a file cache and Memcache?
Here's my idea:
* Retrieve cache details from Memcache
* If cache not expired, use file from file cache
* If cache is expired, remove file from file cache and store cached file from Memcache instead.
* If cached file doesn't exist, retrieve it from Memcache or recompile/create new cache version
So:
- We get the benefit of APC OpCode cache on cached files
- If the server recompiles the template, it's immediately distributed through Memcache
Any thoughts/comments/feedback? |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Wed May 25, 2011 11:01 am Post subject: |
|
|
There are two separate considerations to this issue. One being "generate once, use on any machine" (distribution) and "avoid slow HDD".
You could use an NFS mount to store your cache on disk. You'd then have them just as accessible to every machine in your cluster, as if you were using memcache or a database.
Distributing files to multiple machines is not (always) the primary goal though. Reducing the disk I/O is a much bigger issue for load-heavy environments. Disks are slow. They're the slowest storage option you've got.
If you compare RAM / Disk / CPU utilization on your hardware, you'll probably notice your CPU being the least utilized component. This may either be because of the machine having nothing to do, or the machine having to wait on something. If your CPU utilization is rather low compared to the system's load, you probably shouldn't worry about eval() (being a computing thing), but worry about I/O issues regarding disk and network.
The problem with APC's OpCode-Cache is that it can only process scripts from disk. And, unless you specified apc.stat = 0, it will re-check mtime of the source to automatically update the cache if necessary. Very much like Smarty's compile_check option.
BTW:
The only accelerator I could find babbling something about caching eval()ed code was eAccelerator. I'm not sure if it actually caches OpCodes of eval()ed strings or the results of their execution, though. |
|
Back to top |
|
emt Smarty Regular
Joined: 10 Dec 2009 Posts: 43
|
Posted: Wed May 25, 2011 11:32 am Post subject: |
|
|
You are making some good points.
Let me briefly explain my goals:
- Generate once, having all servers in the cluster using the updated template
- Speed of delivery of the page (whilst still retaining the flexibility & power of Smarty)
The service will be hosted in the Cloud with various different providers (can't afford downtime like Amazon had recently!).
Adding more servers is therefore easy when disk I/O becomes a real issue.
I am loath to use NFS because of past experience with this. I am looking for a solution that is a relatively no-brainer to implement; with NFS things become much more complicated to trouble-shoot when stuff starts going wrong.
I am therefore planning to use Membase as the back-end for Memcache and have various servers in the different data centres.
So my thinking is (correctly or wrongly) that if I have 100 requests per second, that using an APC stored file (yes, with apc.stat = 0) would be faster than having eval executed 100 times per second.
This will of course be properly tested in a cloud environment before we commit to a final solution.
Interesting about eAccelerator, btw, will look into this more although in previous testing I have found eAccelerator to be much slower than APC. |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Wed May 25, 2011 11:41 am Post subject: |
|
|
The assumption that reading caches from APC is faster than eval() is not necessarily true. If you have many cache hits (say per generated cache file at least 20 hits [guessed, needs measuring!]), you may outweigh the overhead of pulling stuff from memcache to disk and shoving it into apc before including the file.
You should also note, that there's a small overhead on every reading request as well. You'd want to store the cache-content and cache-mtime seperately in memcache. You'll have to store the cache-mtime of your local copy on disk to APC as well. Otherwise you don't have the ability to fetch mtime from memcache, fetch mtime from apc, compare and decide to include or reload the cache-content.
I would be very interested in some numbers regarding this approach. If the read/write ratio to make up for the overhead is small enough, we might actually consider building this idea into the cache core. |
|
Back to top |
|
emt Smarty Regular
Joined: 10 Dec 2009 Posts: 43
|
Posted: Wed May 25, 2011 12:45 pm Post subject: |
|
|
Good points.
I will definitely carry out some tests and report back my findings on this. I'll do it in a cloud environment so we get "real world" figures. Will be using Nginx and PHP-FPM too so a fair bit of the web server overhead will be reduced too. |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
|
Back to top |
|
|