diff --git a/README.md b/README.md index 7ebf9a3..2233f6c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ -# An up-to-date Smarty V4.3.5 versus Twig V3.8.0 benchmark [19 February 2024] +# An Smarty versus Twig benchmark -An *opinionated* comparison benchmark of the latest versions of Smarty v4 and Twig v3. - -TL;DR: Smarty is slower than Twig, Twig is faster than Smarty. Don't trust benchmarks from years ago. +An *opinionated* comparison benchmark of the latest versions of Smarty v5 and Twig v3. ## Opinionated How? @@ -13,14 +11,6 @@ The main differences from other benchmarks you might run into: XSS trouble. * Doing a benchmark that _disables auto-escaping_ can hide performance problems in a part of the template engine you *definitely* want to be using. -* This test is being performed in 2017, which means we're not even going to bother with PHP5 - * A *lot* of things are different in PHP now, for example, objects have better performance characteristics in PHP 5.4+ (https://gist.github.com/nikic/5015323) - -Most other benchmarks I've seen date from around 2011 or 2012. That's ancient in web-development terms. And unfortunately, -I've seen a few PHP coders get caught out, choose Smarty because "it's faster" (or so says one benchmark), and end up without -escaping throughout their templates. - -Yes, authors should probably know to escape their output. But, equally, a single oversight shouldn't result in a vulnerability. ## Templates @@ -35,19 +25,23 @@ The test templates are pretty simple: Don't take my word for it: * `composer install` -* `php bench.php smarty` or `php bench.php twig` or `php bench.php twig_reuse` +* `php bench.php smarty`, `php bench.php smarty_reuse`, `php bench.php twig` or `php bench.php twig_reuse` + +Or, if you want to change the number of iterations (defaults to 100.000): + +* `php bench.php smarty 42`, `php bench.php smarty 999999` ## Results -With Smarty 4.3.5 and Twig 3.8.0, on PHP 8.3, 100000 iterations, compile time ignored, cache warmed, my machine, best time -of dozens of runs each: +With Smarty 5.4.0 and Twig 3.11.0, on PHP 8.3, 1.000.000 iterations, compile time ignored, cache warmed, my machine: -Benchmark | Time Taken ---- | --- -twig | 1.0 seconds -twig_reuse | 0.8 seconds -smarty | 1.7 seconds +| Benchmark | Time Taken | +|--------------|-------------| +| twig | 9.2 seconds | +| twig_reuse | 8.5 seconds | +| smarty | 9.5 seconds | +| smarty_reuse | 8.8 seconds | -See the code for the difference between the twig and twig_reuse scenarios (basically: using the same Twig_TemplateWrapper instance, versus -loading the template again. I'm not sure there's an equivalent for Smarty, but I'd be happy to include one if there is.) +See the code for the difference between the normal and reuse scenarios (basically: using the same Template instance, versus +loading the template again.) diff --git a/bench.php b/bench.php index 34cae6d..c46fd48 100755 --- a/bench.php +++ b/bench.php @@ -3,7 +3,7 @@ require __DIR__ . '/vendor/autoload.php'; -function benchmark(string $type, int $iterations = 100000) +function benchmark(string $type, int $iterations) { echo 'Benchmarking ' . $type . "\n"; @@ -37,25 +37,34 @@ function setup($type) { switch ($type) { case 'smarty': - $smarty = new Smarty(); - $smarty->escape_html = true; - $smarty->compile_check = false; + $smarty = new Smarty\Smarty(); + $smarty->setEscapeHtml(true); + $smarty->setCompileCheck(false); $smarty->setCacheDir(__DIR__ . '/cache'); $smarty->setCompileDir(__DIR__ . '/cache'); return $smarty; + + case 'smarty_reuse': + $smarty = new Smarty\Smarty(); + $smarty->setEscapeHtml(true); + $smarty->setCompileCheck(false); + $smarty->setCacheDir(__DIR__ . '/cache'); + $smarty->setCompileDir(__DIR__ . '/cache'); + return $smarty->createTemplate('index.html.smarty'); + case 'twig': - $loader = new \Twig\Loader\FilesystemLoader('templates'); - - return new \Twig\Environment($loader, [ - 'cache' => __DIR__ . '/cache', - ]); + $loader = new \Twig\Loader\FilesystemLoader('templates'); + + return new \Twig\Environment($loader, [ + 'cache' => __DIR__ . '/cache', + ]); case 'twig_reuse': - $loader = new \Twig\Loader\FilesystemLoader('templates'); - - $env = new \Twig\Environment($loader, [ - 'cache' => __DIR__ . '/cache', - ]); + $loader = new \Twig\Loader\FilesystemLoader('templates'); + + $env = new \Twig\Environment($loader, [ + 'cache' => __DIR__ . '/cache', + ]); return $env->load('index.html.twig'); default: @@ -67,9 +76,14 @@ function benchmarkOnce($type, $instance, $data) { switch ($type) { case 'smarty': - /** @var Smarty $instance */ + /** @var Smarty\Smarty $instance */ $instance->assign($data); return $instance->fetch('index.html.smarty'); + case 'smarty_reuse': + /** @var Smarty\Template $instance */ + $instance->assign($data); + return $instance->fetch(); + case 'twig': /** @var Twig_Environment $instance */ $template = $instance->load('index.html.twig'); @@ -87,4 +101,5 @@ function benchmarkOnce($type, $instance, $data) exec('mkdir cache'); $type = $argv[1] ?? null; -benchmark($type); +$iterations = (int) ($argv[2] ?? 100000); +benchmark($type, $iterations); diff --git a/composer.json b/composer.json index 3442cca..31be12a 100644 --- a/composer.json +++ b/composer.json @@ -3,8 +3,8 @@ "description": "Benchmark of Smarty versus Twig", "type": "project", "require": { - "smarty/smarty": "^4.3", - "twig/twig": "^3.8" + "smarty/smarty": "^5.4", + "twig/twig": "^3.11" }, "license": "MIT", "authors": [