0Pricing
PHP Academy · Leçon

Modèle de concurrence de PHP

Comprenez les entrées-sorties bloquantes et les situations où l’asynchrone est utile.

Modèle de concurrence de PHP est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage PHP Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours PHP Academy comprend 4 leçons au total.

PHP est synchrone par défaut

Le PHP classique exécute une requête par processus, de haut en bas, avec des entrées-sorties bloquantes. Un appel à file_get_contents() vers une API lente fige tout le script jusqu’à l’arrivée des octets. Le modèle sans état partagé (un processus vierge par requête, dont l’état est détruit à la fin) est merveilleusement simple — mais cela signifie qu’un seul processus de traitement ne peut faire qu’une seule chose à la fois. Cette leçon montre dans quels cas cela pose problème et dans quels cas l’asynchrone aide.

Mesurer les entrées-sorties bloquantes

Observez le temps écoulé, dominé par l’attente et non par le calcul. Trois requêtes séquentielles d’une seconde prennent environ trois secondes, même si le processeur reste inactif pendant tout ce temps.

<?php
$start = microtime(true);
foreach (['a', 'b', 'c'] as $job) {
    usleep(1_000_000); // simulate a 1s blocking network call
    echo "done $job\n";
}
printf("elapsed: %.2fs\n", microtime(true) - $start); // ~3.00s

Dépendant du processeur ou des entrées-sorties

La concurrence n’aide que pour les tâches dépendantes des entrées-sorties — le temps passé à attendre le réseau, le disque ou la base de données. Pour les tâches dépendantes du processeur (hachage, redimensionnement d’images, analyse), un seul thread est déjà saturé ; l’asynchrone ne fait qu’ajouter le coût de planification. Commencez par établir le diagnostic :

  • Nombreux appels HTTP ou requêtes de base de données lents → l’asynchrone est très avantageux.
  • Boucles numériques serrées → utilisez le parallélisme (processus ou threads), et non une boucle d’événements.

Comment PHP a évolué jusqu’à présent

Historiquement, PHP a évolué grâce à la concurrence au niveau des processus : PHP-FPM maintient un pool de processus de traitement, chacun gérant une requête à la fois, tandis que le système d’exploitation les multiplexe. Il s’agit d’une véritable concurrence entre les requêtes, mais elle n’apporte rien à l’intérieur d’une requête : avec du code bloquant classique, vous ne pouvez toujours pas répartir 50 appels d’API en parallèle dans un seul gestionnaire.

L’idée de la boucle d’événements

Le PHP asynchrone introduit une boucle d’événements : un seul fil d’exécution qui enregistre les opérations d’E/S comme non bloquantes, puis s’endort dans stream_select()/epoll jusqu’à ce que l’une d’elles soit prête, en déclenchant des fonctions de rappel à mesure que les données arrivent. Un seul fil d’exécution jongle avec des milliers de connexions parce qu’il ne reste jamais inactif à attendre sur une seule d’entre elles.

<?php
// Conceptual loop: poll many non-blocking streams at once
$streams = openManyNonBlockingSockets();
while ($streams) {
    $read = $streams; $write = $except = [];
    stream_select($read, $write, $except, null); // sleeps until ANY is ready
    foreach ($read as $s) {
        handleReadyStream($s); // runs only the sockets that have data now
    }
}

Coopératif, non préemptif

Le PHP asynchrone est coopératif : les tâches s’exécutent jusqu’à céder volontairement la main à un point d’E/S. Il n’y a pas de préemption, donc un long appel bloquant ou une boucle serrée qui sollicite le CPU bloque toute la boucle — toutes les autres tâches sont privées de temps d’exécution. Règle d’or : n’appelez jamais de fonctions bloquantes (sleep, PDO bloquant, file_get_contents) à l’intérieur d’une tâche de la boucle d’événements. Utilisez les équivalents asynchrones de la boucle.

Trois approches en PHP

Le PHP moderne propose une boîte à outils par couches :

  • Fibres (PHP 8.1, noyau) — une primitive de bas niveau permettant de mettre en pause et de reprendre une pile d’appels. C’est un élément de base, pas un cadre complet.
  • ReactPHP / Amp — des boucles d’événements de l’espace utilisateur fondées sur des flux (et désormais sur les Fibres) pour les E/S non bloquantes, sans extensions.
  • Swoole / OpenSwoole — une extension C fournissant des coroutines, un serveur haute performance et des appels bloquants interceptés.

Déterminez ce qui est disponible à l’exécution avant de choisir une stratégie.

<?php
echo 'Fibers: ' . (class_exists('Fiber') ? 'yes' : 'no'), PHP_EOL;
echo 'Swoole ext: ' . (extension_loaded('swoole') ? 'yes' : 'no'), PHP_EOL;
echo 'parallel ext: ' . (extension_loaded('parallel') ? 'yes' : 'no'), PHP_EOL;
echo 'PHP ' . PHP_VERSION, PHP_EOL;

Les promesses représentent des valeurs futures

Avant les Fibres, le PHP asynchrone exposait les résultats en attente sous forme de promesses : un espace réservé pour une valeur qui sera résolue ultérieurement. Vous y attachez des fonctions de rappel avec then(). Cela fonctionne, mais entraîne des chaînes imbriquées ; les Fibres permettent aux bibliothèques de dissimuler cela derrière un await à l’apparence synchrone.

<?php
use React\Promise\Promise;

$promise = new Promise(function ($resolve) {
    // resolved later when I/O completes
    $resolve(42);
});
$promise->then(function ($value) {
    echo "got $value\n";
});

Concurrence ou parallélisme

Soyez précis :

  • Concurrence — de nombreuses tâches en cours, entrelacées sur un seul fil d’exécution (boucle d’événements). Idéale pour les E/S.
  • Parallélisme — de nombreuses tâches exécutées simultanément sur plusieurs cœurs (processus, extension parallel, travailleurs de tâches Swoole). Nécessaire pour les traitements sollicitant le CPU.

Une boucle d’événements fournit de la concurrence, pas du parallélisme. L’extrait ci-dessous montre un parallélisme au niveau des processus avec proc_open — trois travailleurs s’exécutent simultanément dans des processus OS distincts.

<?php
$procs = [];
foreach (range(1, 3) as $i) {
    // Each worker is a separate OS process -> real parallelism
    $procs[] = proc_open(
        "php -r 'usleep(500000); echo \"worker $i done\\n\";'",
        [1 => ['pipe', 'w']], $pipes
    );
}
foreach ($procs as $p) { proc_close($p); }
echo "all workers launched in parallel\n";

Quand NOT recourir à l’asynchrone

L’asynchrone a un coût : un travailleur à longue durée de vie signifie que PHP n’efface plus l’état entre les requêtes ; les fuites mémoire, les caches statiques et l’obsolescence des connexions deviennent votre problème. Si un gestionnaire de requête effectue une seule requête à la base de données puis renvoie le résultat, PHP-FPM est plus simple et tout aussi rapide. Recourez à l’asynchrone lorsque vous avez besoin d’une multiplication des E/S, de WebSockets/interrogations longues, de diffusion en continu ou d’un serveur persistant.

Parallélisme réel : extension de parallélisme et processus

Pour les traitements sollicitant le CPU et répartis entre plusieurs tâches, PHP peut exécuter un véritable parallélisme au niveau de l’OS. L’extension parallel crée des fils d’exécution travailleurs dotés d’une mémoire isolée ; sinon, proc_open/pcntl_fork créent des processus. Contrairement à une boucle d’événements, ces mécanismes utilisent plusieurs cœurs simultanément — c’est l’outil adapté lorsque le goulot d’étranglement est le calcul plutôt que l’attente.

<?php
// Requires ext-parallel — runs tasks on separate threads/cores
use parallel\Runtime;

$runtime = new Runtime();
$future = $runtime->run(function (): int {
    $sum = 0;
    for ($i = 0; $i < 1_000_000; $i++) $sum += $i; // CPU work on another core
    return $sum;
});
echo $future->value(), PHP_EOL;

Vérification rapide

Que se passe-t-il si vous appelez la fonction bloquante sleep(2) dans une tâche de la boucle d’événements ?

Récapitulatif

Vous disposez désormais d’un modèle mental de la concurrence en PHP :

  • Le PHP par défaut est synchrone, bloquant et sans partage d’état ; FPM évolue en répartissant les requêtes, pas le travail au sein d’une même requête.
  • L’asynchrone facilite les traitements limités par les E/S grâce à une boucle d’événements à fil d’exécution unique utilisant des flux non bloquants.
  • Le modèle est coopératif — ne bloquez jamais la boucle ; les longs traitements sollicitant le CPU nécessitent le parallélisme, pas la concurrence.
  • La boîte à outils PHP : Fibres (primitive), ReactPHP/Amp (boucles de l’espace utilisateur + promesses), Swoole (extension de coroutines).

Questions Fréquemment Posées

La leçon « Modèle de concurrence de PHP » est-elle gratuite ?

Oui — le texte complet de « Modèle de concurrence de PHP » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours PHP Academy, passe à CoddyKit PRO. Le cours PHP Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Modèle de concurrence de PHP » ?

Comprenez les entrées-sorties bloquantes et les situations où l’asynchrone est utile. Tu pratiques PHP Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer PHP Academy ?

Aucune expérience préalable n'est requise. PHP Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Modèle de concurrence de PHP » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon PHP Academy ?

Oui. Chaque leçon PHP Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Modèle de concurrence de PHP
  2. Fibers de PHP 8.1
  3. Boucles d’événements avec ReactPHP
  4. Serveurs hautes performances avec Swoole
← Retour à PHP Academy