Performance improvement: use plain array instead of ArrayObject for variable storage into templates

This commit is contained in:
Ivan Shalganov 2014-01-27 23:58:14 +04:00
parent 05a4991a5d
commit 7759df8453
4 changed files with 25 additions and 20 deletions

View File

@ -17,7 +17,7 @@ use Fenom\Template;
*/
class Fenom
{
const VERSION = '1.4';
const VERSION = '1.5';
/* Actions */
const INLINE_COMPILER = 1;

View File

@ -41,18 +41,18 @@ class Compiler
$tpl->addDepend($inc);
$var = $tpl->tmpVar();
if($p) {
return $var.' = (array)$tpl; $tpl->exchangeArray(' . self::toArray($p) . '+'.$var.'); ?>' . $inc->getBody() . '<?php $tpl->exchangeArray('.$var.'); unset('.$var.');';
return $var.' = $var; $var = ' . self::toArray($p) . ' + $var; ?>' . $inc->getBody() . '<?php $var = '.$var.'; unset('.$var.');';
} else {
return $var.' = (array)$tpl; ?>' . $inc->getBody() . '<?php $tpl->exchangeArray('.$var.'); unset('.$var.');';
return $var.' = $var; ?>' . $inc->getBody() . '<?php $var = '.$var.'; unset('.$var.');';
}
} elseif(!$tpl->getStorage()->templateExists($name)) {
throw new \LogicException("Template $name not found");
}
}
if($p) {
return '$tpl->getStorage()->getTemplate(' . $cname . ')->display(' . self::toArray($p) . '+(array)$tpl);';
return '$tpl->getStorage()->getTemplate(' . $cname . ')->display(' . self::toArray($p) . ' + $var);';
} else {
return '$tpl->getStorage()->getTemplate(' . $cname . ')->display((array)$tpl);';
return '$tpl->getStorage()->getTemplate(' . $cname . ')->display($var);';
}
}

View File

@ -9,7 +9,6 @@
*/
namespace Fenom;
use Fenom;
use Symfony\Component\Yaml\Exception\RuntimeException;
/**
* Primitive template
@ -195,12 +194,13 @@ class Render extends \ArrayObject
/**
* Get internal macro
* @param $name
* @throws \RuntimeException
* @return mixed
*/
public function getMacro($name)
{
if (empty($this->_macros[$name])) {
throw new RuntimeException('macro not found');
throw new \RuntimeException('macro not found');
}
return $this->_macros[$name];
}
@ -212,9 +212,9 @@ class Render extends \ArrayObject
*/
public function display(array $values)
{
$this->exchangeArray($values);
$this->_code->__invoke($this);
return $this->exchangeArray(array());
// $this->exchangeArray($values);
$this->_code->__invoke($values, $this);
return $values;
}
/**

View File

@ -312,7 +312,7 @@ class Template extends Render
*/
public function tmpVar()
{
return sprintf('$t%u_%d', $this->_crc, $this->i++);
return sprintf('$t%x_%x', $this->_crc, $this->i++);
}
/**
@ -411,7 +411,7 @@ class Template extends Render
$macros = array();
foreach ($this->macros as $m) {
if ($m["recursive"]) {
$macros[] = "\t\t'" . $m["name"] . "' => function (\$tpl) {\n?>" . $m["body"] . "<?php\n}";
$macros[] = "\t\t'" . $m["name"] . "' => function (\$var, \$tpl) {\n?>" . $m["body"] . "<?php\n}";
}
}
return "array(\n" . implode(",\n", $macros) . ")";
@ -426,7 +426,7 @@ class Template extends Render
*/
private function _getClosureSource()
{
return "function (\$tpl) {\n?>{$this->_body}<?php\n}";
return "function (\$var, \$tpl) {\n?>{$this->_body}<?php\n}";
}
/**
@ -440,8 +440,11 @@ class Template extends Render
{
if (!$this->_code) {
// evaluate template's code
// $code = ("\$this->_code = " . $this->_getClosureSource() . ";\n\$this->_macros = " . $this->_getMacrosArray() . ';');
// file_put_contents('/tmp/last.tpl', $code);
eval("\$this->_code = " . $this->_getClosureSource() . ";\n\$this->_macros = " . $this->_getMacrosArray() . ';');
if (!$this->_code) {
// exit;
throw new CompileException("Fatal error while creating the template");
}
}
@ -798,14 +801,14 @@ class Template extends Render
public function parseVariable(Tokenizer $tokens, $var = null)
{
if(!$var) {
$var = '$tpl["' . substr( $tokens->get(T_VARIABLE), 1) . '"]';
$var = '$var["' . substr( $tokens->get(T_VARIABLE), 1) . '"]';
$tokens->next();
}
while ($t = $tokens->key()) {
if ($t === ".") {
$tokens->next();
if ($tokens->is(T_VARIABLE)) {
$key = '[ $tpl["' . substr($tokens->getAndNext(), 1) . '"] ]';
$key = '[ $var["' . substr($tokens->getAndNext(), 1) . '"] ]';
} elseif ($tokens->is(Tokenizer::MACRO_STRING)) {
$key = '["' . $tokens->getAndNext() . '"]';
} elseif ($tokens->is(Tokenizer::MACRO_SCALAR)) {
@ -1121,7 +1124,7 @@ class Template extends Render
} else {
$_str = "";
}
$_str .= '$tpl["' . substr($tokens->current(), 1) . '"]';
$_str .= '$var["' . substr($tokens->current(), 1) . '"]';
$tokens->next();
if ($tokens->is($stop)) {
$tokens->skip();
@ -1285,14 +1288,16 @@ class Template extends Render
throw new InvalidUsageException("Macro '$name' require '$arg' argument");
}
}
$n = sprintf('%u_%d', crc32($this->_name), $this->i++);
// $n = sprintf('%x_%x', crc32($this->_name), $this->i++);
if ($recursive) {
$recursive['recursive'] = true;
$body = '$tpl->getMacro("' . $name . '")->__invoke($tpl);';
return '$tpl->getMacro("' . $name . '")->__invoke('.Compiler::toArray($args).', $tpl);';
} else {
$body = '?>' . $macro["body"] . '<?php';
// $body = '? >' . $macro["body"] . '<?php';
$vars = $this->tmpVar();
return $vars . ' = $var; $var = ' . Compiler::toArray($args) . ';' . PHP_EOL . '?>' .
$macro["body"] . '<?php' . PHP_EOL . '$var = '.$vars.'; unset(' . $vars . ');';
}
return '$_tpl' . $n . ' = $tpl->exchangeArray(' . Compiler::toArray($args) . ');' . PHP_EOL . $body . PHP_EOL . '$tpl->exchangeArray($_tpl' . $n . '); /* X */ unset($_tpl' . $n . ');';
}
/**