Durant le développement d'un site internet, nous nous retrouvons régulièrement confrontés au besoin d'inclure un fragment de template complexe dans plusieurs pages. Un bon exemple serait un formulaire de newsletter ou un menu. Mais y a-t-il une méthode objectivement optimale pour procéder ?
Lors d'un hackathon organisé chez Novaway, j'ai décidé de m'attaquer à cette question. J'ai donc appliqué une méthode scientifique dans le but d'apporter des éléments de réponse circonstanciés à cette problématique récurrente.
Pour chaque méthode, le but va être d'afficher une page avec un certain nombre de formulaires très simples. Les formulaires ont été choisis car simples à implémenter, mais nécessitant un temps de calcul du coté Symfony (pas juste un écho).
Les tests ont été réalisés sur Billon Immobilier, un projet existant (donc avec tous les chargements de configuration).
nocache
Tous les formulaires sont directement créés dans le Controller principal.
with_render
Tous les formulaires sont créés chacun par un appel à {{ render(controller) }} de twig.
with_twig_extension
Tous les formulaires sont créés chacun par un appel à une Twig_extension, qui crée et rend le formulaire grâce au combo FormFactory \ TwigEngine.
with_esi
Tous les formulaires sont créés chacun par un appel à {{ render(controller) }} de twig dans un ESI .
Le reverse proxy utilisé est celui de Symfony par soucis de simplicité
On étudiera les comportements en modifiant ces variables :
Parameters ---------- --------------- ----------------- ------------ Elt per page Number of tests Random max --------------- ----------------- ------------ 5000 1 10 --------------- ----------------- ------------ First simulation : no randomization ----------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 4383.6 with_render 11760.2 with_twig_extension 4921.4 with_esi 5586.4 --------------------- ---------- Second simulation : randomization --------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 4355.6 with_render 10431.2 with_twig_extension 4739.9 with_esi 5478.1 --------------------- ----------
Classement :
Conclusion : la méthode with_render est loin derrière. Les deux méthodes sans SubRequests sont les plus performantes, avec la solution des TwigExtensions un peu derrière.
La méthode avec les ESI est 10 à 20% moins performante, mais reste acceptable.
Parameters ---------- --------------- ----------------- ------------ Elt per page Number of tests Random max --------------- ----------------- ------------ 100 10 10 --------------- ----------------- ------------ First simulation : no randomization ----------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 2506.3 with_render 11423.4 with_twig_extension 7215.2 with_esi 2657 --------------------- ---------- Second simulation : randomization --------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 2655.9 with_render 13129.8 with_twig_extension 7054.7 with_esi 2680.9 --------------------- ----------
Classement :
Conclusion : la méthode `with_render` est toujours loin derrière. La méthode `nocache` est toujours devant, mais pas significativement devant les ESI. Cette fois les `with_twig_extension` sont bien derrière les deux autres méthodes compétitives.
Parameters ----------- --------------- ----------------- ------------ Elt per page Number of tests Random max --------------- ----------------- ------------ 1 1000 10 --------------- ----------------- ------------ First simulation : no randomization ----------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 178118 with_render 184976.4 with_twig_extension 184623.2 with_esi 161696.8 --------------------- ---------- Second simulation : randomization --------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 172071.7 with_render 176265.8 with_twig_extension 179850.4 with_esi 157780.5 --------------------- ----------
Cette mesure est la plus intéressante, pouvant représenter un élément de footer par exemple.
Classement :
Conclusion : cette fois, la méthode des ESI est environ 15% plus performante que les autres, qui sont beaucoup plus proches. La différence entre le `with_render` et le `with_twig_extension` est bien plus ténue, le rapport s'inversant même dans le cas de la randomization : cela peut ceci dit être un artefact.
La plage de randomization étant bien plus importante que le nombre de tests, on peut s'attendre à ce que rien ne soit caché.
Parameters ---------- --------------- ----------------- ------------ Elt per page Number of tests Random max --------------- ----------------- ------------ 1 100 1000000 --------------- ----------------- ------------ First simulation : no randomization ----------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 17572.1 with_render 17771.8 with_twig_extension 18026.1 with_esi 15987.7 --------------------- ---------- Second simulation : randomization --------------------------------- --------------------- ---------- Type Duration --------------------- ---------- nocache 16740 with_render 17595 with_twig_extension 17594.4 with_esi 19878.7 --------------------- ----------
Classement :
Conclusion : comme attendu, dans cette configuration sans randomization les ESI arrivent avant. Avec randomization, ils sont assez loin derrière (même si on n'a pas les résultats catastrophiques de with_render dans les premiers tests).
Il est à noter que le nombre de mesures n'est pas suffisant pour pouvoir statuer sur les conclusions. Cependant, les quelques résultats testés semblent tous indiquer les mêmes tendances.
Toutes les alternatives à "générer le code dans la méthode principale du Controller" ont un coût (test1). Par contre, dès qu'il est possible de cacher ces fragments, le coût de la méthode with_esi diminue, devenant même inférieur à la méthode nocache quand le nombre de requêtes devient grand (test2 et test3).
On voit également que plus le nombre de tests augmente et le nombre d'éléments par page diminue, plus les méthodes with_render et with_twig_extension ont des performances proches.
De plus, il est important de considérer que le fragment utilisé pour le test est très léger pour le processeur. Ces écarts devraient normalement s'accentuer si le traitement nécessaire devient plus lourd.
Par ailleurs, on est ici dans le cas d'un reverse cache proxy peu performant (celui de Symfony). On peut imaginer obtenir des performances optimisées avec une meilleure solution. Néanmoins, si les fragments sont très différents (et donc non cacheable), les performances des ESI deviennent bien pires que les autres méthodes.