Twig: accélérer la génération de ses templates avec include (2/2)

Ce deuxième article fais suite à un premier post donnant des solutions rapides pour optimiser la génération des templates. Il est le fruit d’optimisation déjà utilisé sur des sites en production qui possédait un taux de latence trop important.

Nous utilisons tous les includes de Twig pour déporter ou factoriser nos vues. Mais peut-être n’avez-vous jamais compris pourquoi nous avions la possibilité de passer des paramètres, alors qu’un include de base hérite des variables du contexte en cours.

1
{% include "ProjectMyBundle:Sub:template.html.twig" %}

Souvent nous utilisons cette notation. Dans ce cas, l’include donnera une copie de toutes nos variables à notre template. Cela n’est pas toujours nécessaire, et nous avons tort de copier l’intégralité de nos variables.

Intérêt de l’option « only »

Je me suis longtemps demandé qu’elle était l’intérêt de cette option. D’ailleurs il faut dire que la documentation ne donne pas beaucoup d’élément. Vous pouvez aller jeter un coup d’œil sur la documentation des includes Twig. Elle donne peu d’élément mais elle donne surtout un inconvénient et aucun avantage : se passer de certaines variables. Vue de cette manière, cela n’est pas rentable ; pourquoi je devrais me passer de certaines variables.

Mettons en œuvre nos includes ! Admettons que notre template de base ait 5 variables et que j’inclue un template qui n’utilise qu’une seule de ces variable, voilà la notation qui sera préférable.

1
{% include "ProjectMyBundle:Sub:template.html.twig" with {"object": myVar} only %}

De cette manière seul une variable « object » sera disponible dans mon template. Cela limite la copie de variable inutile, et donc d’allocation de mémoire (gain de temps et de consommation mémoire).

Code et cas d’utilisation

1
2
3
4
5
6
// Controller
// Ici le génère un template en passant un variable imposante (une collection) contenant tous les objets pour une table donnée
public function testAction() {
$objects = $this->container->get("doctrine.orm.default_entity_manager")->getRepository("ProjectMyBundle:Test")->findAll();
return array("objects" => $objects);
}

Nous effectuons une boucle sur notre collection et nous donnons un template chaque itération de la collection au template. Dans ce cas, chaque fois que l’on fait appelle à l’intégration d’un template, l’intégralité des variables sont copiées ainsi que celles qui sont passées avec l’option « with ». Dans notre premier cas on pourrait très bien imaginer accéder à notre collection (objects) ainsi que notre itération en cours (object).

1
2
3
4
5
{# Template 1 #}
{% for object in objects %}
{% include "ProjectMyBundle:Sub:template.html.twig" with {"object": object} %}
{% endfor %}

Dans notre deuxième cas, j’active l’option only ce qui permet de copier uniquement les variables passés en paramètres. Facile ?

1
2
3
4
5
{# Template 2 #}
{% for object in objects %}
{% include "ProjectMyBundle:Sub:template.html.twig" with {"object": object} only %}
{% endfor %}

Benchmark

J’ai réalisé les tests avec les templates et le code donnés dans la partie ci-dessus. J’ai effectuer avec 5 itérations de chaque template, en pensant à vider le cache avant chaque premier test.

Benchmark des performances Twig avec l'utilisation des includes

Avec ce graphe, on voit bien le chargement est globalement plus long pour ceux qui n’utilisent pas l’option only. La différence a tendance à se réduire après la mise en cache. Cela est dû au fait que mon template est petit et que peu de variable sont utilisés. Dans des cas plus appliqués on note des gains pouvant aller jusqu’à 30%.

Ici, si on fait une moyenne des valeurs, on atteint une différence moyenne de 9 ms (48,6 - 39,6 = 9). On peut donc calculer un gain approximatif de 20% même si cela est à relativiser dans notre cas puisque le premier shot est terriblement long sans l’utilisation de « only ».

Conclusion

Dans notre exemple, on remarque qu’il est facile (à condition d’être méthodique) de limiter le temps de génération des templates. Malgré nos résultats qui montrent que le temps de génération tend à se réduire, le gain serait bien plus rapide sur des templates plus costaud et utilisant plus de variable que dans notre cas d’utilisation.