Multi-Threading en PHP5
L'article rédigé par Martin Roest nous montre à quel point il peut-être facile de jouer avec plusieurs processus en même temps, même en PHP.
J'ai personnellement été très séduit par la simplicité, mais je trouve que l'on pouvais encore faire plus simple : une petite classe :)
L'utilité d'un tel code se trouve sur des scripts de traitement, tel qu'un remaniement de base de donnée, une modifications sur plusieurs fichiers, etc. Par contre, il est important de savoir que la gestion des processus tel qu'il est utilisé ici ne fonctionne pas sous Windows, et qu'il n'est pas conseillé d'appeler ce script depuis un environnement type Apache.
En gros et pour faire simple, ce type de script s'utilise en ligne de commande (php-cli) et dans un environnement Unix, type cron.
Pour vous prouver l'efficacité de mes dires, voici un code bateau qui utilise 5 processus simultanés pour exécuter un script :
<?php
require_once ('ProcessManager.php');
function doBigWork ($iWork) {
echo 'Sleeping for Work N° '.$iWork."\n";
sleep (20);
}
try {
// We instanciate the ProcessManager with 5 childs
$oPM = new ProcessManager (5);
}
catch (Exception $oE) {
die ('Your configuration does not support "pcntl" methods.');
}
for ($i = 0; $i &:t; 12; $i++) {
// It could happen that the script couldn't fork a process. In that case, an Exception would be raised
try {
$oPM->fork ('doBigWork', array ($i));
}
catch (Exception $oE) {
echo 'Using non forked way :'."\n";
doBigWork ($i);
}
}
?>Au final, sans utiliser plusieurs processus, ce code aurait pris 12*20 = 240 secondes. Avec 5 enfants, le temps de travail est divisé par ... 5, soit 48 secondes ! Quand même !
Bien entendu, vous pouvez augmenter le nombre d'enfant, tout dépendra des ressources que consomment votre fonction de travail (histoire de ne pas tuer votre machine (je l'ai fait pendant les tests :p)).
Une dernière modification qui serait sympathique, c'est d'inclure les fonctions lambdas dans la méthode fork, au lieu de l'appel à une méthode en utilisant le call_user_func_array. Mais ma configuration actuelle de Php n'est pas encore en 5.3, donc je ne peux ni jouer avec les closures, ni avec les fonctions lambdas :p Peut-être plus tard ? :)
Voici la classe à proprement parler :