- use output buffers for better performance and less memory usage

This commit is contained in:
uwetews
2015-08-19 01:09:08 +02:00
parent 6087ac5de0
commit 8292a3581c
7 changed files with 87 additions and 50 deletions

View File

@@ -4,6 +4,7 @@
- load seldom used Smarty API methods dynamically to reduce memory footprint
- cache template object of {include} if same template is included several times
- convert debug console processing to object
- use output buffers for better performance and less memory usage
06.08.2015
- avoid possible circular object references caused by parser/lexer objects

View File

@@ -817,7 +817,22 @@ class Smarty extends Smarty_Internal_TemplateBase
// set caching in template object
$_template->caching = $this->caching;
// fetch template content
return $_template->render(true, false, $display);
$level = ob_get_level();
try {
$_smarty_old_error_level = isset($this->error_reporting) ? error_reporting($this->error_reporting) : null;
ob_start();
$result = $_template->render(true, false, $display);
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
}
return $result === null ? ob_get_clean() : $result;
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
/**

View File

@@ -282,9 +282,11 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
//$compiler->suppressNocacheProcessing = true;
}
if (isset($_assign)) {
$_output .= " \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}'));\n";
$_output .= "ob_start();\n";
$_output .= "\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n";
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(ob_get_clean());\n";
} else {
$_output .= "echo \$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n";
$_output .= "\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n";
}
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
@@ -303,9 +305,11 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
// was there an assign attribute
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(\$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl}));\n";
$_output .= "ob_start();\n";
$_output .= "\$_smarty_tpl->getSubTemplate($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl});\n";
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(ob_get_clean());\n";
} else {
$_output .= "echo \$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl});\n";
$_output .= "\$_smarty_tpl->getSubTemplate($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl});\n";
}
if ($update_compile_id) {
$_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";

View File

@@ -151,14 +151,34 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @param bool $_display true: display, false: fetch
*
* @throws Exception
* @throws SmartyException
* @return string rendered template output
* @return string
* @throws \Exception
*/
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null)
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $_display = false)
{
return isset($template) ? $this->smarty->fetch($template, $cache_id, $compile_id, $parent) : $this->render(true, false, false);
if (isset($template)) {
return $this->smarty->fetch($template, $cache_id, $compile_id, $parent, $_display);
} else {
// fetch template content
$level = ob_get_level();
try {
$_smarty_old_error_level = isset($this->smarty->error_reporting) ? error_reporting($this->smarty->error_reporting) : null;
ob_start();
$result = $this->render(true, false, $_display);
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
}
return $result === null ? ob_get_clean() : $result;
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
}
/**
@@ -232,7 +252,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$this->tpl_vars = $tpl_vars;
$this->config_vars = $config_vars;
}
$_smarty_old_error_level = isset($this->smarty->error_reporting) ? error_reporting($this->smarty->error_reporting) : null;
// check URL debugging control
if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {
$this->smarty->_debug->debugUrl($this);
@@ -260,9 +279,9 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if (!isset($this->compiled)) {
$this->loadCompiled();
}
$content = $this->compiled->render($this);
$this->compiled->render($this);
} else {
$content = $this->source->renderUncompiled($this);
$this->source->renderUncompiled($this);
}
if ($parentIsTpl && !empty($this->tpl_function)) {
$this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function);
@@ -275,7 +294,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if ($this->smarty->debugging) {
$this->smarty->_debug->start_cache($this);
}
$this->cached->updateCache($this, $content, $no_output_filter);
$this->cached->updateCache($this, $no_output_filter);
$compile_check = $this->smarty->compile_check;
$this->smarty->compile_check = false;
if ($parentIsTpl) {
@@ -285,7 +304,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$this->cached->process($this, true);
}
$this->smarty->compile_check = $compile_check;
$content = $this->getRenderedTemplateCode($this->cached->unifunc);
$this->getRenderedTemplateCode($this->cached->unifunc);
if ($this->smarty->debugging) {
$this->smarty->_debug->end_cache($this);
}
@@ -303,25 +322,23 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if ($this->smarty->debugging) {
$this->smarty->_debug->start_cache($this);
}
$content = $this->cached->render($this);
$this->cached->render($this);
if ($this->smarty->debugging) {
$this->smarty->_debug->end_cache($this);
}
}
$content = null;
if ((!$this->caching || $this->cached->has_nocache_code || $this->source->recompiled) && !$no_output_filter &&
(isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))
) {
$content = Smarty_Internal_Filter_Handler::runFilter('output', $content, $this);
}
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
$content = Smarty_Internal_Filter_Handler::runFilter('output', ob_get_clean(), $this);
}
// display or fetch
if ($display) {
if ($this->caching && $this->smarty->cache_modified_check) {
$this->cached->cacheModifiedCheck($this, $content);
$this->cached->cacheModifiedCheck($this, isset($content) ? $content : ob_get_clean());
} else {
echo $content;
echo isset($content) ? $content : ob_get_clean();
}
if ($this->smarty->debugging) {
$this->smarty->_debug->end_template($this);
@@ -361,7 +378,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
}
}
// return cache content
return $content;
return $content === null ? null: $content;
}
}
@@ -377,7 +394,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
{
$level = ob_get_level();
try {
ob_start();
if (empty($unifunc) || !is_callable($unifunc)) {
throw new SmartyException("Invalid compiled template for '{$this->template_resource}'");
}
@@ -397,12 +413,16 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if (isset($this->smarty->security_policy)) {
$this->smarty->security_policy->exitTemplate();
}
return ob_get_clean();
return null;
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
array_shift($this->_capture_stack);
if (isset($this->smarty->security_policy)) {
$this->smarty->security_policy->exitTemplate();
}
throw $e;
}
}
@@ -470,7 +490,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj)
{
$tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj);
return $tpl->render();
$tpl->render();
}
/**
@@ -563,7 +583,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$this->smarty->_debug->start_template($tpl);
$this->smarty->_debug->start_render($tpl);
}
$output = $tpl->getRenderedTemplateCode($content_func);
$tpl->getRenderedTemplateCode($content_func);
if ($this->smarty->debugging) {
$this->smarty->_debug->end_template($tpl);
$this->smarty->_debug->end_render($tpl);

View File

@@ -208,7 +208,7 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base
if (!$this->processed) {
$this->process($_template);
}
return $_template->getRenderedTemplateCode($this->unifunc);
$_template->getRenderedTemplateCode($this->unifunc);
}
/**
@@ -269,31 +269,33 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base
*
* @throws SmartyException
*/
public function updateCache(Smarty_Internal_Template $_template, $content, $no_output_filter)
public function updateCache(Smarty_Internal_Template $_template, $no_output_filter)
{
$content = ob_get_clean();
$_template->cached->has_nocache_code = false;
// get text between non-cached items
$cache_split = preg_split("!/\*%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*/!s", $content);
// get non-cached items
preg_match_all("!/\*%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*/!s", $content, $cache_parts);
$output = '';
$content = '';
// loop over items, stitch back together
foreach ($cache_split as $curr_idx => $curr_split) {
// escape PHP tags in template content
$output .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*>)/', "<?php echo '\$1'; ?>\n", $curr_split);
$content .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*>)/', "<?php echo '\$1'; ?>\n", $curr_split);
if (isset($cache_parts[0][$curr_idx])) {
$_template->cached->has_nocache_code = true;
$output .= $cache_parts[1][$curr_idx];
$content .= $cache_parts[1][$curr_idx];
}
}
if (!$no_output_filter && !$_template->compiled->has_nocache_code &&
(isset($_template->smarty->autoload_filters['output']) ||
isset($_template->smarty->registered_filters['output']))
) {
$output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template);
$content = Smarty_Internal_Filter_Handler::runFilter('output', $content, $_template);
}
// write cache file content
$this->writeCachedContent($_template, $output);
$this->writeCachedContent($_template, $content);
ob_start();
}
/**

View File

@@ -206,7 +206,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
if (isset($_template->cached)) {
$_template->cached->file_dependency = array_merge($_template->cached->file_dependency, $this->file_dependency);
}
return $_template->getRenderedTemplateCode($this->unifunc);
$_template->getRenderedTemplateCode($this->unifunc);
}
/**
@@ -222,6 +222,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
$_template->source->compileds = array();
$this->file_dependency = array();
$this->tpl_function = array();
$this->includes = array();
$this->nocache_hash = null;
$this->unifunc = null;
// compile locking

View File

@@ -202,7 +202,9 @@ class Smarty_Template_Source
list($name, $type) = Smarty_Resource::parseResourceName($template_resource, $smarty->default_resource_type);
$resource = Smarty_Resource::load($smarty, $type);
// if resource is not recompiling and resource name is not dotted we can check the source cache
if (($smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) && !$resource->recompiled && !(isset($name[1]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/'))) {
if (($smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) && !$resource->recompiled &&
!(isset($name[1]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/'))
) {
$unique_resource = $resource->buildUniqueResourceName($smarty, $name);
if (isset($smarty->source_objects[$unique_resource])) {
return $smarty->source_objects[$unique_resource];
@@ -221,8 +223,11 @@ class Smarty_Template_Source
// may by we have already $unique_resource
$is_relative = false;
if (!isset($unique_resource)) {
$is_relative = isset($name[1]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/') && ($type == 'file' || (isset($_template->parent->source) && $_template->parent->source->type == 'extends'));
$unique_resource = $resource->buildUniqueResourceName($smarty, $is_relative ? $source->filepath . $name : $name);
$is_relative = isset($name[1]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/') &&
($type == 'file' ||
(isset($_template->parent->source) && $_template->parent->source->type == 'extends'));
$unique_resource = $resource->buildUniqueResourceName($smarty, $is_relative ? $source->filepath .
$name : $name);
}
$source->unique_resource = $unique_resource;
// save in runtime cache if not relative
@@ -243,18 +248,7 @@ class Smarty_Template_Source
*/
public function renderUncompiled(Smarty_Internal_Template $_template)
{
$level = ob_get_level();
ob_start();
try {
$this->handler->renderUncompiled($_template->source, $_template);
return ob_get_clean();
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
/**