Nous avions déjà assisté à la conférence de Kevin Dunglas sur FrankenPHP lors de la SymfonyCon Disneyland Paris 2022, et avons pu profiter d'une seconde conférence adressée lors du DrupalCamp de Rennes en 2024.
Bien qu'intéressant et prometteur, le projet semblait toutefois bien jeune, et nous ne pouvions imaginer proposer une solution avec si peu de retour d'expériences pour remplacer des stacks éprouvées auprès de nos clients.
FrankenPHP, c'est quoi ?
FrankenPHP est un serveur d'applications PHP écrit en Go. Il s'appuie sur le serveur Caddy et propose un certain nombre de fonctionnalités dont les principales sont :
- Des performances accrues
- Fournir un serveur de qualité production
- Créer des binaires autonomes et auto-executables
- Une simplicité de configuration
- Proposer des fonctionnalités actuelles non prises en compte par les systèmes actuels (103 Early hints, Temps réel, etc)
Et FrankenPHP avec Drupal ?
Initié en 2022, le repository github permettant de configurer un FrankenPHP avec Drupal s'est affiné suite au DrupalCamp de Rennes.
Bonne nouvelle, cela fonctionne ! On arrive alors sans effort à faire fonctionner un Drupal avec FrankenPHP.
Et les performances dans tout ça ?
Edit 04/04/2024 : Corrections suite a affinage des tests.
Les tests ont été réalisés depuis et sur un poste de développement avec Docker. Les chiffres sont donc à prendre pour ce qu'ils sont et n'ont pour seul objectif que de se donner un ordre de grandeur des différences entre notre stack habituelle et frankenPHP.
- Test réalisés via l'image docker Docker-Jmeter.
- Stack habituelle : Un container PHP-FPM + Nginx
- Stack FrankenPHP : Un container FrankenPHP
Lors des tests, seuls les containers de la stack à tester sont allumés.
Pour les tests, nous avons installé sur chacune des stacks un Drupal avec le profil d'exemple Umami et y cherchons la chaine "Vegan" sur des tests de perfs pendant 600 secondes avec un appel HTTP (pas de HTTPS), un seul thread et aucun délai. La base de données utilisée dans les 2 cas est une base de données MariaDB située dans un container des stacks respectives.
Les tests ont été réalisés 2 fois pour s'assurer de la cohérence des tests.
Les tests ont été réalisés en tant qu'utilisateur anonyme avec les caches d'activés et sans les caches.
La configuration est la suivante pour les tests avec les caches désactivés de manière à solliciter d'avantage de calcul :
Configuration de settings.nocache.php inclut dans settings.php :
$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
$settings['container_yamls'][] = $app_root . '/sites/default/services.nocache.yml';
Configuration de services.nocache.yml :
parameters:
twig.config:
cache: false
services:
cache.backend.null:
class: Drupal\Core\Cache\NullBackendFactory
Tests avec la stack PHP-FPM
Commençons par la stack que nous utilisons habituellement, à savoir un container PHP-FPM incluant un NGINX configuré et optimisé pour Drupal.
En anonyme, avec les caches désactivés
Nous arrivons donc à un résultat de :
- Nombre d'appels : 480
- Temps minimum de réponse : 181ms
- Temps maximum de réponse : 282ms
- Temps moyen de réponse : 202.22ms
En anonyme, avec les caches activés
Nous arrivons donc à un résultat de :
- Nombre d'appels : 569
- Temps minimum de réponse : 3ms
- Temps maximum de réponse : 45ms
- Temps moyen de réponse : 5.43ms
Tests avec FrankenPHP
Pour rappel, nous utilisons FrankenPHP avec mariadb (au moment des tests, le github proposait postgresql par défaut, nous verrons ce cas plus tard).
En anonyme, avec les caches désactivés
Nous arrivons donc à un résultat de :
- Nombre d'appels : 471
- Temps minimum de réponse : 212ms
- Temps maximum de réponse : 329ms
- Temps moyen de réponse : 226.18ms
En anonyme, avec les caches activés
Nous arrivons donc à un résultat de :
- Nombre d'appels : 568
- Temps minimum de réponse : 4ms
- Temps maximum de réponse : 32ms
- Temps moyen de réponse : 6.36ms
Comparatif des résultats
NGINX + PHP-FPM | FrankenPHP | |
Nombre d'appels | 480 | 471 |
Temps Min. en ms | 181 | 212 |
Temps Max. en ms | 282 | 329 |
Temps moyen en ms | 202.22 | 226.18 |
NGINX + PHP-FPM | FrankenPHP | |
Nombre d'appels | 569 | 568 |
Temps Min. en ms | 3 | 4 |
Temps Max. en ms | 45 | 32 |
Temps moyen en ms | 5.43 | 6.36 |
Peu de différence entre les 2, mais léger mieux pour NGINX + PHP-FPM, mitigé par le fait que la configuration de cette stack a été d'avantage optimisée et éprouvée que FrankenPHP qui est configuré par défaut (pas de mode worker) et qu'il n'en est qu'à ses début.
Les tests sont ce qu'ils sont, c'est à dire pas grand chose : les tests sont très basiques, effectués sur la même machine, aucune optimisation spécifique, utilisation des caches de Drupal... Mais permettent tout de même de voir une belle différence entre les 2 systèmes, suffisantes pour pousser les tests avec FrankenPHP.
Allons plus loin, et postgreSQL ?
Les premiers tirs ont été effectués avec postgreSQL sur FrankenPHP, la configuration fournie par défaut sur le repo étant postgreSQL.
Voici donc pour information les tests avec FrankenPHP uniquement et PostgreSQL.
FrankenPHP + PostgreSQL | FrankenPHP + MariaDB | |
Nombre d'appels | 556 | 565 |
Temps Min. en ms | 13 | 4 |
Temps Max. en ms | 51 | 29 |
Temps moyen en ms | 28.64 | 10.01 |
On voit donc une différence cette fois de x2 a x3 en temps de réponse en faveur de mariaDB.