From 3d37a88f0b5e0696df8b410f4ab2a86cae0df177 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Mon, 18 Aug 2014 05:00:16 -0700 Subject: [PATCH 1/4] Replace is_object/is_array with switch on gettype When checking multiple types, this is ~10% slower in the worst case, and ~30-33% faster for the average and best case. See #218 --- src/Mustache/Context.php | 31 +++++++++++++++++++------------ src/Mustache/Template.php | 27 +++++++++++++++------------ 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/Mustache/Context.php b/src/Mustache/Context.php index 0115ff0..b87c99c 100644 --- a/src/Mustache/Context.php +++ b/src/Mustache/Context.php @@ -172,19 +172,26 @@ class Mustache_Context private function findVariableInStack($id, array $stack) { for ($i = count($stack) - 1; $i >= 0; $i--) { - if (is_object($stack[$i]) && !($stack[$i] instanceof Closure)) { + switch (gettype($stack[$i])) { + case 'object': + if (!($stack[$i] instanceof Closure)) { + // Note that is_callable() *will not work here* + // See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods + if (method_exists($stack[$i], $id)) { + return $stack[$i]->$id(); + } elseif (isset($stack[$i]->$id)) { + return $stack[$i]->$id; + } elseif ($stack[$i] instanceof ArrayAccess && isset($stack[$i][$id])) { + return $stack[$i][$id]; + } + } + break; - // Note that is_callable() *will not work here* - // See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods - if (method_exists($stack[$i], $id)) { - return $stack[$i]->$id(); - } elseif (isset($stack[$i]->$id)) { - return $stack[$i]->$id; - } elseif ($stack[$i] instanceof ArrayAccess && isset($stack[$i][$id])) { - return $stack[$i][$id]; - } - } elseif (is_array($stack[$i]) && array_key_exists($id, $stack[$i])) { - return $stack[$i][$id]; + case 'array': + if (array_key_exists($id, $stack[$i])) { + return $stack[$i][$id]; + } + break; } } diff --git a/src/Mustache/Template.php b/src/Mustache/Template.php index 4d1273d..f6e5f2e 100644 --- a/src/Mustache/Template.php +++ b/src/Mustache/Template.php @@ -113,19 +113,22 @@ abstract class Mustache_Template */ protected function isIterable($value) { - if (is_object($value)) { - return $value instanceof Traversable; - } elseif (is_array($value)) { - $i = 0; - foreach ($value as $k => $v) { - if ($k !== $i++) { - return false; - } - } + switch (gettype($value)) { + case 'object': + return $value instanceof Traversable; - return true; - } else { - return false; + case 'array': + $i = 0; + foreach ($value as $k => $v) { + if ($k !== $i++) { + return false; + } + } + + return true; + + default: + return false; } } From df67052626c0768875c3272c94a6d28458720847 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Mon, 18 Aug 2014 09:01:57 -0700 Subject: [PATCH 2/4] Use reference to current stack frame (saves quite a few array lookups) See #218 --- src/Mustache/Context.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Mustache/Context.php b/src/Mustache/Context.php index b87c99c..b16b400 100644 --- a/src/Mustache/Context.php +++ b/src/Mustache/Context.php @@ -172,24 +172,26 @@ class Mustache_Context private function findVariableInStack($id, array $stack) { for ($i = count($stack) - 1; $i >= 0; $i--) { - switch (gettype($stack[$i])) { + $frame = &$stack[$i]; + + switch (gettype($frame)) { case 'object': - if (!($stack[$i] instanceof Closure)) { + if (!($frame instanceof Closure)) { // Note that is_callable() *will not work here* // See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods - if (method_exists($stack[$i], $id)) { - return $stack[$i]->$id(); - } elseif (isset($stack[$i]->$id)) { - return $stack[$i]->$id; - } elseif ($stack[$i] instanceof ArrayAccess && isset($stack[$i][$id])) { - return $stack[$i][$id]; + if (method_exists($frame, $id)) { + return $frame->$id(); + } elseif (isset($frame->$id)) { + return $frame->$id; + } elseif ($frame instanceof ArrayAccess && isset($frame[$id])) { + return $frame[$id]; } } break; case 'array': - if (array_key_exists($id, $stack[$i])) { - return $stack[$i][$id]; + if (array_key_exists($id, $frame)) { + return $frame[$id]; } break; } From c0bd7efe3930aa3da0b10de20a454aedc2da0541 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Mon, 18 Aug 2014 16:56:32 -0700 Subject: [PATCH 3/4] No need for elseif with returns :) /cc @keradus --- src/Mustache/Compiler.php | 10 ++++++---- src/Mustache/Context.php | 8 ++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Mustache/Compiler.php b/src/Mustache/Compiler.php index 9161c64..285287c 100644 --- a/src/Mustache/Compiler.php +++ b/src/Mustache/Compiler.php @@ -631,11 +631,13 @@ class Mustache_Compiler { if ($id === '.') { return 'last'; - } elseif (strpos($id, '.') === false) { - return 'find'; - } else { - return 'findDot'; } + + if (strpos($id, '.') === false) { + return 'find'; + } + + return 'findDot'; } const IS_CALLABLE = '!is_string(%s) && is_callable(%s)'; diff --git a/src/Mustache/Context.php b/src/Mustache/Context.php index b16b400..db03acc 100644 --- a/src/Mustache/Context.php +++ b/src/Mustache/Context.php @@ -181,9 +181,13 @@ class Mustache_Context // See https://github.com/bobthecow/mustache.php/wiki/Magic-Methods if (method_exists($frame, $id)) { return $frame->$id(); - } elseif (isset($frame->$id)) { + } + + if (isset($frame->$id)) { return $frame->$id; - } elseif ($frame instanceof ArrayAccess && isset($frame[$id])) { + } + + if ($frame instanceof ArrayAccess && isset($frame[$id])) { return $frame[$id]; } } From 8449681a37f1729be96cd57e2ac298ffde138832 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Mon, 18 Aug 2014 16:58:19 -0700 Subject: [PATCH 4/4] One more unnecessary else/return combo. --- src/Mustache/Compiler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mustache/Compiler.php b/src/Mustache/Compiler.php index 285287c..8d079fb 100644 --- a/src/Mustache/Compiler.php +++ b/src/Mustache/Compiler.php @@ -609,9 +609,9 @@ class Mustache_Compiler { if ($this->customEscape) { return sprintf(self::CUSTOM_ESCAPE, $value); - } else { - return sprintf(self::DEFAULT_ESCAPE, $value, var_export($this->entityFlags, true), var_export($this->charset, true)); } + + return sprintf(self::DEFAULT_ESCAPE, $value, var_export($this->entityFlags, true), var_export($this->charset, true)); } /**