La vérité sur l'asynchrone en PHP : Fibers, epoll et PHP 8.6
J'ai travaillé avec Laravel pendant des années. J'utilisais du PHP synchrone. Une requête arrive, le processus s'exécute, et la réponse est envoyée. Je n'ai jamais eu besoin de code asynchrone.
Puis, j'ai lu des choses sur la nouvelle API de Polling de PHP 8.6. Cela a changé ma vision des choses.
Voici ce que j'ai appris sur le fonctionnement interne de l'asynchrone.
Le problème d'I/O
Lorsque vous appelez une API, votre processus PHP attend.
Exemple :
$response = Http::get('https://api.example.com');
Si cet appel prend 300 ms, votre CPU ne fait rien pendant 300 ms. Il reste en état de veille. C'est ce qu'on appelle l'I/O bloquante.
Si vous avez trois appels API :
- API A : 300 ms
- API B : 400 ms
- API C : 200 ms
Total séquentiel : 900 ms. Total asynchrone : 400 ms (le temps de l'appel le plus long).
L'asynchrone permet à votre processus d'effectuer d'autres tâches en attendant les données.
Select vs. epoll
Pour faire de l'asynchrone, vous devez savoir quel socket a des données prêtes.
1. select()
PHP utilise stream_select() depuis la version 4. Cela fonctionne en demandant au noyau de surveiller une liste de sockets.
Le problème : chaque fois que des données arrivent, vous devez scanner à nouveau toute la liste. C'est une "taxe de rescan". Il y a également une limite d'environ 1024 connexions.
2. epoll (Linux) / kqueue (macOS)
Ce sont des fonctionnalités du noyau. Au lieu de scanner une liste, le noyau conserve une liste de sockets prêts. Il vous indique uniquement quels sockets spécifiques sont prêts. Cela permet de passer à des milliers de connexions sans travail supplémentaire.
epoll n'est pas une fonctionnalité de PHP. C'est une fonctionnalité de Linux. Go, Rust et Node.js l'utilisent tous.
Fibers : Le bouton pause
PHP 8.1 a introduit les Fibers. Je pensais que les Fibers se réveilleraient d'elles-mêmes. Ce n'est pas le cas.
Une Fiber est comme une vidéo en pause. Elle reste en pause jusqu'à ce que quelqu'un appelle $fiber->resume().
Une boucle d'événements (Event Loop) n'est qu'un morceau de code PHP qui décide quand appeler resume().
L'I/O asynchrone nécessite trois éléments :
- Pause : Fibers (cœur de PHP 8.1)
- Décider : L'Event Loop (code PHP pur)
- Savoir : Kernel Polling (epoll/kqueue)
Avant PHP 8.6, PHP possédait les parties "Pause" et "Décider", mais la partie "Savoir" reposait sur l'ancien select() ou sur des extensions C lentes.
PHP 8.6 comble cette lacune. Il intègre une API de Polling native au cœur du langage. Désormais, PHP peut utiliser epoll ou kqueue directement sans extensions supplémentaires.
L'essentiel à retenir
Si vous utilisez Laravel avec PHP-FPM, vous n'avez rien à changer aujourd'hui.
Mais comprenez bien ceci : l'asynchrone n'est pas magique. C'est simplement une manière intelligente de gérer le temps d'attente.
Arrêtez de simplement consommer du code. Lancez un script simple. Cassez-le. C'est ainsi que l'on apprend vraiment.
