Le site arthur.bebou.netlib.re - retour accueil
git clone git://bebou.netlib.re/arthur.bebou
Log | Files | Refs |
index.sh (15183B)
1 #! page 2 3 title: Benchmark de Francium 4 author: Arthur Pons 5 publication: 2023-03-11 6 description: Quelques statistiques sur le site de Katzele 7 sectionmd: main 8 9 # Benchmark et critique des performances de Francium 10 11 ## Le benchmark 12 13 J'ai eu l'idée d'écrire cette note en entendant parler d'11ty, un générateur de 14 site statique. Il est écrit sur leur site 15 16 > Fast Builds and even Faster Web Sites 17 18 Et on trouve une petite animation qui présente qu'11ty construit 4000 19 fichiers markdown en 2s, plus rapide que qu'Astro en 20 secondes, Gatbsy en 30 20 secondes etc. Le site omet qu'Hugo est plus rapide mais soit. 21 22 Ces résultats proviennent de [ce 23 benchmark](https://github.com/zachleat/bench-framework-markdown). 24 25 Et Francium ? Testons d'abord les performances de cmark et lowdown, les deux 26 parseur de markdown qui nous utilisons. En prenant les 4000 fichiers markdown 27 du benchmark et en lançant les commandes : 28 29 time find -name '*.md' | xargs -n1 -P0 sh -c 'lowdown "$1" > "$1".html' -- 30 xargs -n1 -P0 sh -c 'lowdown "$1" > "$1".html' -- 4,84s user 1,05s system 307% cpu **2,291** total 31 32 et 33 34 time find -name '*.md' | xargs -n1 -P0 sh -c 'cmark "$1" > "$1".html' -- 35 xargs -n1 -P0 sh -c 'lowdown "$1" > "$1".html' -- 4,84s user 1,05s system 307% cpu **1,914** total 36 37 On tombe sur des temps d'environ deux secondes. Je trouvais surprenant que ces 38 deux logiciels, écrits en C et dont le seul but est de convertir du md en html 39 ne soient pas plus rapides qu'Hugo. Marc m'a rappelé que cette commande fait un 40 fork par fichier et les forks c'est "couteux". 41 42 > Un fork c'est la création d'un nouveau processus par un autre. Nos commandes 43 > seront un processus qui, pour chaque fichier en créera un nouveau pour faire 44 > sa traduction. Créer un nouveau processus a un coût fixe. Il serait donc plus 45 > performant de créer un minimum de processus qui gèrent un maximum de fichiers 46 > chacun. 47 48 En l'occurence cmark peut prendre plusieurs fichiers en argument, on peut donc 49 écrire 50 51 time cmark *.md 52 cmark *.md 0,08s user 0,07s system 29% cpu 0,528 total 53 54 ou pour lowdown tout concaténer 55 56 time cat *.md | lowdown 57 lowdown 0,15s user 0,07s system 32% cpu 0,689 total 58 59 Dans les deux cas on s'économise le fait de devoir créer 4000 fichiers mais pas 60 celui d'écrire les données pour les voir dans la console. D'ailleurs avec : 61 62 time cmark *.md /dev/null 63 cmark *.md > /dev/null 0,08s user 0,07s system 29% cpu 0,093 total 64 65 on voit que la majorité du temps est passé à écrire le résultat. 66 67 J'identifie avec le code suivant 68 69 for i in $(seq 1 4000) 70 do 71 echo $i > $i.txt 72 done 73 ./test 0,03s user 0,17s system 99% cpu 0,199 total 74 75 que cela prend un peu moins de 0,2 secondes de créer 4000 fichiers presque 76 vides[^1] ce qui voudrait dire que l'on a la découpe approximative suivante : 77 78 | opération | temps (s) | 79 |---|---| 80 |traiter les données|0,1| 81 |créer les fichiers|0,2| 82 |écrire les données|0,22| 83 84 En réalité j'en sais rien, je connais pas assez bien linux pour savoir si je 85 mesure les choses comme il faut. Prenez tout ça avec des pincettes. 86 87 Quoi qu'il en soit nous apprenons de ce test que Francium ne pourra pas aller 88 plus vite qu'environ une demie seconde pour 4000 fichiers. Pour en faire un 89 benchmark assez équivalent j'ai retiré tous les alias de page, sauf %S et 90 modifié les pages md du dépôt de benchmark pour qu'elles n'aient plus le 91 92 --- 93 title: blablabla 94 --- 95 96 et leur ajouter le shebang 97 98 #! page 99 100 et les rendre exécutables. 101 102 > J'ai fait ça avec 103 > 104 > find -name '*.md' | xargs -n1 -P0 sed -i 's/^/#! page\n/;2,4d' 105 > chmod 755 ./* 106 107 J'ai vérifié au préalable, le titre n'est pas pris en compte dans le benchmark. 108 Du moins l'HTML généré par Hugo et 11ty a une balise `<title>` vide. 109 Une fois que tout est prêt on construit le site comme on le fait habituellement 110 avec Francium[^2] (version qui utilise lowdown) : 111 112 time make -B -j 113 make -B -j 30,29s user 8,31s system 302% cpu **12,741** total 114 115 On est donc sur du six fois plus lent que la simple conversion en HTML depuis 116 lowdown. Tentons de comprendre pourquoi en bidouillant, faute de savoir comment 117 correctement diagnostiquer ce genre de choses. 118 119 Retirer les shebang et modifier le makefile pour faire 120 121 ./page machin.md 122 123 ne change rien en terme de performance. 124 125 Supprimer l'appel à `install` en faisant directement une redirection semble 126 économiser environ une seconde. 127 128 Supprimer l'appel à page en demandant à makefile de directement utiliser 129 lowdown et en supprimant les heredoc `%S` (en gros ce qu'on a fait au début 130 mais avec l'overhead de make) fait tomber le temps d'exécution à 3,7 secondes. 131 C'est donc quelque part dans page que l'on perd de la performance. 132 133 J'ai ensuite repris depuis le début en supprimant la gestion des sections. Cela 134 revient à s'économiser la création d'un dossier temporaire et d'un fichier 135 temporaire[^3] par article. Ne plus créer le fichier temporaire qu'il faut 136 ensuite relire pour insérer son contenu dans le layout fait gagner environ 2 137 secondes, make ne prend plus qu'environ 9,5 secondes. Ne plus créer le dossier 138 temporaire fait gagner 3 secondes supplémentaires pour descendre à 6,5 secondes 139 environ. 140 141 Il semblerait donc que notre façon de gérer le layout soit responsable de 3 142 secondes d'overhead sur 4000 fichiers. Pour que la comparaison tienne à peu 143 près la route j'ai modifié le template pour qu'il soit identique à celui généré 144 par Hugo. Je m'arrête là dans l'exploration des performances de Francium. 145 146 On en retient qu'à la louche et avec mes outils de diagnostiques très 147 approximatifs, ce qui coûte est : 148 149 | Modification | Temps (s) | 150 |---|---| 151 | overhead make | 1,7 | 152 | la création du dossier temporaire | 2 | 153 | la création puis la lecture du fichier temporaire par section | 3 | 154 | l'appel à install | 1 | 155 | le template | 3 | 156 157 Ce qui ajoutés bout à bout explique la différence entre les deux secondes de 158 lowdown et les 12/13 de Francium. 159 160 Résultats finaux : 161 162 | Générateur | Temps (s) | 163 |---|---| 164 | Hugo | 1,6 | 165 | 11ty | 2 | 166 | Francium (sans sections) | 6 | 167 | Francium | 12 | 168 | Le reste | 20+ | 169 170 ## Et alors ? 171 172 Francium tel qu'il existe pour le site de Katzele est 6 fois plus lent que les 173 deux générateurs de sites statiques les plus rapides et plus rapide que tous les 174 autres. Dans une version allégée, pour un site avec une seule section que l'on 175 souhaite alimenter de contenu il n'est "que" trois fois plus lent. 176 177 C'est significatif mais à mettre au regard du temps d'ingénieurie investit. Il 178 est probable que le temps passé à construire Francium dans son ensemble est un 179 ou deux ou trois ordres de grandeur inférieur au temps passé à rendre Hugo et 180 11ty performants. 181 182 De plus la comparaison de performances de logiciels est compliquée et 183 hasardeuse. Déjà parce que cela dépend du matériel sur lequel les logiciels 184 sont testés. Ensuite parce que les couvertures fonctionnelles ne sont pas les 185 mêmes. Nous avons vu que l'intégration de fonctionnalités supplémentaires dans 186 Francium pouvait avoir un fort impact sur sa performance. Qu'en est-il des 187 autres outils ? Hugo et 11ty font *beaucoup* plus de choses que Francium mais 188 le benchmark leur fait générer un site aussi simple que gros. Au vu de leurs 189 performances, ils ne semblent pas ralentir quand leurs très nombreuses 190 fonctionnalités ne sont pas effectivement utilisées. Comment Hugo et 11ty 191 réagiraient-ils si l'on construisait des sites plus complexes ? Et Francium ? 192 En l'absence de réponse à ces questions les benchmarks ne veulent pas dire 193 grand chose. 194 195 Cela dit, pourquoi est-ce que ces logiciels font la promotion de leurs 196 performances sur leurs pages d'accueil ? Au-delà d'une éventuelle volonté de 197 savoir qui a ~~la plus gro~~ le plus rapide, possibilité à ne pas sous-estimer, 198 on pourrait aller regarder du côté des générateurs historiques. On me racontait 199 que fut une époque nombre de générateurs de sites étaient particulièrement 200 "lents". Il fallait attendre possiblement plusieurs dizaines de secondes pour 201 faire la revu de ses modifications ce qui rendait l'itération lente et le 202 travail fastidieux. Pour résoudre ce souci il semblerait que les communautés 203 autour de ces outils aient opté pour de l'ingénierie logicielle supplémentaire 204 faisant appel à nos matériels informatiques modernes très puissants. "Cela 205 prend 30 secondes de reconstruire tout le site pour vérifier le rendu de 206 notre nouvelle page ? Optimisons le code pour que les opérations aillent plus 207 vite et fassent usage de toute la puissance des processeurs pour le faire 208 descendre à deux secondes". 209 210 Ce qui est intéressant c'est qu'en puisant dans une autre culture informatique, 211 comme la notre par exemple, ce n'est pas une autre solution qui aurait été 212 choisie mais le problème qui n'aurait tout simplement existé - ou suffisamment 213 rarement pour que ça n'en soit pas un. 214 215 Illustrons cette idée en trois points : 216 217 1. Dans le monde Unix le système de "build"[^4] traditionnel permet de ne 218 reconstruire que le nécessaire. 219 220 Le système utilisé pour compiler de nombreux programmes dans le monde Unix (et 221 sur lequel Francium se base), make, utilise un graph de dépendance pour savoir 222 ce qui doit être reconstruit et ce qui est encore à jour. Ainsi, si l'on 223 modifie 10 fichiers markdown sur les 4000 il n'est nécessaire de reconstruire 224 que 10 fichiers HTML. A moins d'avoir vraiment besoin de tout reconstruire, 225 pour une raison technique ou parce que l'on a touché à quelque de chose de 226 commun à tout le site (un template par exemple), la question du temps de 227 génération de la totalité d'un si gros site est caduque. La variable 228 qui influe sur la vitesse de construction est dorénavant la quantité de 229 fichiers modifiés et non plus la quantité de fichiers au total. 230 231 A noter que cet avantage n'est pas gratuit, les moteurs de production sont 232 souvent des logiciels assez complexes. L'alternative à priori plus légère et 233 maintenable à cmake et make serait 234 [mk](https://doc.cat-v.org/plan_9/4th_edition/papers/mk). 235 236 Si les personnes impliquées dans les communautés des générateurs de site 237 statique avaient identifié des moteurs tels que make comme judicieux pour leurs 238 besoins alors le problème ne ce serait probablement jamais posé. 239 240 Dans la pratique une configuration parmi d'autres qui permettrait d'itérer 241 rapidement serait d'avoir une fenêtre vim d'ouverte sur le fichier qui nous 242 intéresse et depuis le dossier dans lequel le makefile se trouve, et une autre 243 fenêtre avec l'aperçu du fichier html. Dans vim on met la configuration 244 "autowrite" (aw de son petit nom) à vraie en faisant `set aw` et lorsque l'on 245 veut vérifier nos modifs faire `:make!`. Suffit ensuite de rafraichir la page 246 dans le navigateur. 247 248 > autowrite permet d'indiquer à vim que vous voulez qu'il enregistre les 249 > modifications apportées au lancement de tout un tas de commandes dont make. 250 > Voir `:help autowrite` pour plus d'infos. 251 252 Un petit map pour n'avoir à appuyer sur qu'un seul bouton dans vim : 253 254 map <F3>:set aw<CR>:make!<CR><CR> 255 256 2. L'utilisation d'éditeurs de texte s'interfaçant bien avec le système permet 257 de tester des bouts de markdown. 258 259 Toujours en partant du principe que le besoin principal est d'obtenir un 260 feedback rapide sur ce que l'on a écrit, un éditeur tel que vim permet d'y 261 répondre sans jamais toucher à la génération du site. 262 263 Exemple, on a un doute sur la syntaxe des liens (personnellement j'inverse 264 souvent les () et les []), on écrit : 265 266 (un lien)[http://katzele.netlib.re] 267 268 On teste si ça fonctionne en se mettant sur la ligne et en le filtrant avec 269 lowdown - ou markdown ou pandoc ou... - en lançant `:.!lowdown` : 270 271 <p>(un lien)[<a href="http://katzele.netlib.re">http://katzele.netlib.re</a>]</p> 272 273 Ah oui non c'est pas ça 274 275 [un lien](http://katzele.netlib.re) 276 <p><a href="http://katzele.netlib.re">un lien</a></p> 277 278 mieux ! 279 280 Si l'on veut tester plusieurs lignes on peut faire une sélection visuelle sur 281 plusieurs lignes ou remplacer `.` de la commande `:.!lowdown` par un autre range[^5]. 282 283 On peut aussi écrire un heredoc et le filtrer avec sh. En faisant `vip` puis `:!sh` 284 (ce qui va écrire `:'<,'>!sh` dans la ligne de commande, les `'<>` étant les ranges 285 du début jusqu'à la fin de la sélection visuelle) : 286 287 <<. lowdown 288 | Générateur | Temps (s) | 289 |---| 290 | Hugo | 1,6 | 291 | 11ty | 2 | 292 | Francium (sans sections) | 6 | 293 | Francium | 12 | 294 | Le reste | 20+ | 295 . 296 297 et ça va donner 298 299 <p>| Générateur | Temps (s) | 300 |—| 301 | Hugo | 1,6 | 302 | 11ty | 2 | 303 | Francium (sans sections) | 6 | 304 | Francium | 12 | 305 | Le reste | 20+ |</p> 306 307 Ce n'est pas un tableau, réessayons en ajoutant un colonne ligne 2 : 308 309 <<. lowdown 310 | Générateur | Temps (s) | 311 |---|---| 312 | Hugo | 1,6 | 313 | 11ty | 2 | 314 | Francium (sans sections) | 6 | 315 | Francium | 12 | 316 | Le reste | 20+ | 317 . 318 319 et ça donne : 320 321 <table> 322 <thead> 323 <tr> 324 <th>Générateur</th> 325 <th>Temps (s)</th> 326 </tr> 327 </thead> 328 329 <tbody> 330 <tr> 331 <td>Hugo</td> 332 <td>1,6</td> 333 </tr> 334 <tr> 335 <td>11ty</td> 336 <td>2</td> 337 </tr> 338 <tr> 339 <td>Francium (sans sections)</td> 340 <td>6</td> 341 </tr> 342 <tr> 343 <td>Francium</td> 344 <td>12</td> 345 </tr> 346 <tr> 347 <td>Le reste</td> 348 <td>20+</td> 349 </tr> 350 </tbody> 351 </table> 352 353 Sauf que c'est difficile de dire à l'oeil nu si c'est juste. On peut le piper 354 dans lynx et lui demander de dump le résultat dans vim pour voir ce que ça 355 donne : 356 357 <<. lowdown | lynx -stdin --dump 358 | Générateur | Temps (s) | 359 |---|---| 360 | Hugo | 1,6 | 361 | 11ty | 2 | 362 | Francium (sans sections) | 6 | 363 | Francium | 12 | 364 | Le reste | 20+ | 365 . 366 367 Générateur Temps (s) 368 Hugo 1,6 369 11ty 2 370 Francium (sans sections) 6 371 Francium 12 372 Le reste 20+ 373 374 Nickel. 375 376 J'imagine qu'il y a pleins d'autres façons d'obtenir du feedback, que ce soit 377 avec vim ou d'autres outils. Vous pouvez écrire au collectif si vous voulez 378 les partager. Ou mieux encore, écrire sur la liste linux du lug. 379 380 ## Mot de la fin 381 382 Le but de l'article est de mettre en lumière que pour une situation donnée des 383 cultures informatiques différentes peuvent mener à des lectures radicalement 384 différentes. Ce qui est un problème pour un groupe n'en est pas un pour un 385 autre. Ce qui doit donc être produit pour y remédier par le premier n'a pas à 386 l'être pour l'autre. Ce n'est pas sans conséquence. 387 388 Problème ou pas, une autre façon de le voir serait de prendre le problème à 389 l'envers. Plutôt que d'estimer qu'un temps de construction "long" pour un gros 390 site est un problème d'optimisation logiciel, on pourrait estimer que lorsque 391 le temps de construction du site est perçu comme "long" c'est que le site est 392 trop gros. 393 394 [^1]: Peut-être que ça a un gros impact qu'ils ne le soient pas d'ailleurs, je ne sais pas 395 [^2]: Nous utiliserons lowdown à partir d'ici 396 [^3]: Un seul puisque les fichiers markdown du benchmark n'ont pas de "section". Tout va donc au même endroit dans le layout et un seul fichier de section a besoin d'être créé 397 [^4]: moteur de production en bon français semble-t-il 398 [^5]: `.` est le range qui veut dire "la ligne sous le curseur". Voir `:help range` pour plus d'infos