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 class Fenom
{ {
const VERSION = '1.4'; const VERSION = '1.5';
/* Actions */ /* Actions */
const INLINE_COMPILER = 1; const INLINE_COMPILER = 1;

View File

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

View File

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

View File

@ -312,7 +312,7 @@ class Template extends Render
*/ */
public function tmpVar() 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(); $macros = array();
foreach ($this->macros as $m) { foreach ($this->macros as $m) {
if ($m["recursive"]) { 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) . ")"; return "array(\n" . implode(",\n", $macros) . ")";
@ -426,7 +426,7 @@ class Template extends Render
*/ */
private function _getClosureSource() 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) { if (!$this->_code) {
// evaluate template's 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() . ';'); eval("\$this->_code = " . $this->_getClosureSource() . ";\n\$this->_macros = " . $this->_getMacrosArray() . ';');
if (!$this->_code) { if (!$this->_code) {
// exit;
throw new CompileException("Fatal error while creating the template"); throw new CompileException("Fatal error while creating the template");
} }
} }
@ -798,14 +801,14 @@ class Template extends Render
public function parseVariable(Tokenizer $tokens, $var = null) public function parseVariable(Tokenizer $tokens, $var = null)
{ {
if(!$var) { if(!$var) {
$var = '$tpl["' . substr( $tokens->get(T_VARIABLE), 1) . '"]'; $var = '$var["' . substr( $tokens->get(T_VARIABLE), 1) . '"]';
$tokens->next(); $tokens->next();
} }
while ($t = $tokens->key()) { while ($t = $tokens->key()) {
if ($t === ".") { if ($t === ".") {
$tokens->next(); $tokens->next();
if ($tokens->is(T_VARIABLE)) { if ($tokens->is(T_VARIABLE)) {
$key = '[ $tpl["' . substr($tokens->getAndNext(), 1) . '"] ]'; $key = '[ $var["' . substr($tokens->getAndNext(), 1) . '"] ]';
} elseif ($tokens->is(Tokenizer::MACRO_STRING)) { } elseif ($tokens->is(Tokenizer::MACRO_STRING)) {
$key = '["' . $tokens->getAndNext() . '"]'; $key = '["' . $tokens->getAndNext() . '"]';
} elseif ($tokens->is(Tokenizer::MACRO_SCALAR)) { } elseif ($tokens->is(Tokenizer::MACRO_SCALAR)) {
@ -1121,7 +1124,7 @@ class Template extends Render
} else { } else {
$_str = ""; $_str = "";
} }
$_str .= '$tpl["' . substr($tokens->current(), 1) . '"]'; $_str .= '$var["' . substr($tokens->current(), 1) . '"]';
$tokens->next(); $tokens->next();
if ($tokens->is($stop)) { if ($tokens->is($stop)) {
$tokens->skip(); $tokens->skip();
@ -1285,14 +1288,16 @@ class Template extends Render
throw new InvalidUsageException("Macro '$name' require '$arg' argument"); 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) { if ($recursive) {
$recursive['recursive'] = true; $recursive['recursive'] = true;
$body = '$tpl->getMacro("' . $name . '")->__invoke($tpl);'; return '$tpl->getMacro("' . $name . '")->__invoke('.Compiler::toArray($args).', $tpl);';
} else { } 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 . ');';
} }
/** /**