The fastest template engine for PHP
Choosing a template engine for the Comet project, I decided to compare all the engines popular in the PHP community.
Usually the choice is dictated by the framework: fans of Symfony wrap HTML with Twig, the Laravel programmers arm himself with Blade.
But I was interested in the question — how do these options differ in terms of performance? After testing seven engines and one another in pure PHP, I got an answer.
Here the list of popular engines based on GitHub stars and Reddit mentions:
Smarty: github.com/smarty-php/smarty
Plates: github.com/thephpleague/plates
Mustache: github.com/bobthecow/mustache.php
Twig: github.com/twigphp/Twig
Blade: github.com/jenssegers/blade
BladeOne: github.com/EFTEC/BladeOne
Latte: github.com/nette/latte
If you know an interesting option — comment this article, I will add it to the tests. Blade is pretty deeply integrated into Laravel, so I had to take a couple of its standalone implementations. Unfortunately, none of them supports Blade-X components.
To understand the essence of the benchmark, the easiest way is to look at the version of code with pure PHP:
$data = [
(object) [
"code" => 200,
"message" => "OK"
],
(object) [
"code" => 404,
"message" => "Not Found"
],
(object) [
"code" => 500,
"message" => "Internal Server Error"
],
]; $html = '<html><head></head><body>';
foreach ($data as $message) {
$html .= "<p>$message->code : $message->message</p>";
}
$html .= '</body></html>';
This is a synthetic test for outputting an array of three objects into an HTML template containing two properties: HTML code and its brief description.
This is what the analog on Twig looks like:
<html><head></head><body>
{% for message in data %}
<p>{{ message.code }} : {{ message.message }}</p>
{% endfor %}
</body></html>
And Blade looks like this:
<html><head></head><body>
@foreach ($data as $message)
<p>{{ $message->code }} : {{ $message->message }}</p>
@endforeach
</body></html>
The tests were run in the Ubuntu 20.04 / PHP 7.4 / Comet 0.6 on a virtual machine with 4 Ryzen 3600 cores and 4G memory:
wrk --connections=500 --threads=2 --duration=10s http://comet:8080/php
This situation turned out, each graph reflects the average number of requests successfully completed in one second:
Pure PHP — expected first, but unexpectedly, that Blade is already half as much behind! And why is the “light” Plates lagging behind the “powerful” Twig? All frameworks use regular caching, so the results are as close as possible to real ones.
I did not want to overload the reader with an extended analysis of the code and caching strategies of all engines, so if this topic is interesting to you — please write me and I’ll write a sequel.
P.S: Take a look at Comet — one of the fastest and most convenient PHP-framework for creating RESTful APIs and microservices :)