View previous topic :: View next topic |
Author |
Message |
mankyd Smarty Regular
Joined: 04 May 2006 Posts: 92 Location: Boston MA
|
Posted: Wed May 14, 2008 6:17 am Post subject: Performance Tweak I've Made - Is It Safe? |
|
|
We have an extended version of the Smarty class we're using where I work. In this same file, we've defined a handful of plugins and modifiers that we generally use everywhere. Thus, we wrote a registerPlugins() function that simply made a bunch of calls to $this->register_funtion(), $this->register_modifier(), etc. It did this for every new template object we created.
Unfortunately, we discovered this to be one of the slowest parts of our code. I did a little digging, and I believe that I have found a way to optimize this code. Basically, I am guaranteed that the functions associated with the plugins are defined so there seems to be no need for each template to run smarty_core_load_plugins() for them.
To remove this dependency, and thus the need to register the plugins constantly, I overrode the Smarty_Compiler class. I only register my plugins when compiling, not when simply executing templates. I also overrode the _add_plugin() function such that if the plugin being added is a known plugin, it will not be hard-coded into the smarty_core_load_plugin() function.
A basic form of my compiler class is as follows:
Code: | class My_Smarty_Compiler extends Smarty_Compiler {
//getPlugins() returns a list of plugins that I know are defined and good to go
protected static function getPlugins() {
return array('function' =>
array('func' => 'smarty_function_func',
//...
),
'modifier' =>
array('mod' => 'smarty_modifier_mod',
//...
),
'block' =>
array('blck' => 'smarty_block_blck',
//...
),
'prefilter' =>
array('smarty_prefilter_prfltr',
//...
)
);
}
//utility function to take the above data and register it
protected function registerPlugins() {
$plugins = self::getPlugins();
foreach($plugins['function'] as $n => $f)
$this->register_function($n, $f);
foreach($plugins['modifier'] as $n => $f)
$this->register_modifier($n, $f);
foreach($plugins['block'] as $n => $f)
$this->register_block($n, $f);
foreach($plugins['prefilter'] as $f)
$this->register_prefilter($f);
}
//register our plugins before we try to compile files
function _compile_file($resource_name, $source_content, &$compiled_content) {
$this->registerPlugins();
return parent::_compile_file($resource_name, $source_content, $compiled_content);
}
//don't _add_plugin() if the plugin in question is one we consider safe
function _add_plugin($type, $name, $delayed_loading = NULL) {
$plugins = self::getPlugins();
if (!isset($plugins[$type][$name]))
parent::_add_plugin($type, $name, $delayed_loading);
}
} |
I guess my question is: is this safe? Does it work as I hope it does? I know I lose some of the no-cache options for plugins and I know I didn't define all of the plugin-types (though that would be trivial.) I just want to make sure that I'm not going to be hit with some unexpected bug that I'm not seeing. So far, everything seems to be working.
Last edited by mankyd on Mon May 19, 2008 1:59 am; edited 2 times in total |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Wed May 14, 2008 8:18 pm Post subject: |
|
|
Well I am not shure if there are other side effects using this approach.
Another question I have is if you are using caching? If yes you could gain performance by registering your plugins only when the page is not already in the cache because the plugins are only needed when the page has to be renderend. This might be a solution which which is more straight forward and has no side effects. |
|
Back to top |
|
mankyd Smarty Regular
Joined: 04 May 2006 Posts: 92 Location: Boston MA
|
Posted: Wed May 14, 2008 8:49 pm Post subject: |
|
|
Unfortunately template caching is sort of out of the picture for our site. Its too large and dynamic. Many elements could never be cached, and those that could be would require complex logic to achieve proper expiration. Also, we need separate versions of most pages for each user, and with lots of users (think hundreds of thousands and growing) that's a no-go.
So far everything seems to be running smoothly on our development servers. |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Wed May 14, 2008 10:18 pm Post subject: |
|
|
Okay, I understand. So give it a try.... |
|
Back to top |
|
mankyd Smarty Regular
Joined: 04 May 2006 Posts: 92 Location: Boston MA
|
Posted: Fri May 16, 2008 10:38 pm Post subject: |
|
|
I've found one break in this, though it doesn't affect our code base. If you try to run a modifier on an array, it won't work. Smarty's run_mod_handler() function requires all modifiers to be registered. Because we never use this functionality (I've actually coded a prefilter that turns it off) it doesn't affect our code. |
|
Back to top |
|
Celeb Administrator
Joined: 17 Apr 2007 Posts: 1025 Location: Vienna
|
Posted: Sat May 17, 2008 8:28 am Post subject: |
|
|
You don't use modifiers [on arrays]? _________________ Darn computers always do what I tell them to instead of what I want them to do. |
|
Back to top |
|
mankyd Smarty Regular
Joined: 04 May 2006 Posts: 92 Location: Boston MA
|
Posted: Mon May 19, 2008 1:51 am Post subject: |
|
|
We use a lot of modifiers, but we never want to map a modifier to the individual members of an array. 99% of the arrays in our code are simply array of objects that we want to loop over. I can't really think of any cases where array_map() would be useful to us.
I actually coded up a prefilter that does a pretty good job reversing the array_map functionality: http://www.phpinsider.com/smarty-forum/viewtopic.php?t=13394. I kinda wish there was a flag on the compiler that could do what my prefilter does. |
|
Back to top |
|
Celeb Administrator
Joined: 17 Apr 2007 Posts: 1025 Location: Vienna
|
Posted: Mon May 19, 2008 9:02 am Post subject: |
|
|
Ok, I see your point. I actually used it once like this:
Code: | {html_options options=$persons|format_person selected=$selected_person} |
With $persons being an array of arrays each containing the first and last name of a person.
Well now that you've got your prefilter, you don't really need the compiler flag anymore, do you? _________________ Darn computers always do what I tell them to instead of what I want them to do. |
|
Back to top |
|
|