Présentation
PHP a un Multi-Threading complet un soutien dont vous pouvez profiter pleinement de bien des façons. Ont pu démontrer cette capacité de Multi-Threading dans différents exemples :
- Comment utiliser le multi-threading dans les applications PHP
- pcntl exécute le même code plusieurs fois, assistance requise
- Amélioration de l'efficacité du scraper HTML avec pcntl_fork()
Une recherche rapide donnerait des ressources supplémentaires.
Catégories
1 :Requêtes MySQL
MySQL est entièrement multithread et utilisera plusieurs processeurs, à condition que le système d'exploitation les prenne en charge. Il maximiserait également les ressources système s'il était correctement configuré pour les performances.
Un paramètre typique dans le my.ini
qui affectent les performances du thread est :
thread_cache_size = 8
thread_cache_size peut être augmenté pour améliorer les performances si vous avez beaucoup de nouvelles connexions. Normalement, cela ne fournit pas une amélioration notable des performances si vous avez une bonne implémentation de thread. Cependant, si votre serveur voit des centaines de connexions par seconde, vous devez normalement définir thread_cache_size suffisamment élevé pour que la plupart des nouvelles connexions utilisent des threads en cache
Si vous utilisez Solaris alors vous pouvez utiliser
thread_concurrency = 8
thread_concurrency permet aux applications de donner au système de threads une indication sur le nombre souhaité de threads qui doivent être exécutés en même temps.
Cette variable est obsolète depuis MySQL 5.6.1 et est supprimée dans MySQL 5.7. Vous devez le supprimer des fichiers de configuration MySQL chaque fois que vous le voyez, sauf s'il s'agit de Solaris 8 ou d'une version antérieure.
InnoDB : :
Vous n'avez pas de telles limitations si vous utilisez Innodb a le moteur de stockage car il prend entièrement en charge la simultanéité des threads
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Vous pouvez également consulter innodb_read_io_threads
et innodb_write_io_threads
où la valeur par défaut est 4
et il peut être augmenté jusqu'à 64
selon le matériel
Autres :
D'autres configurations à examiner également incluent key_buffer_size
, table_open_cache
, sort_buffer_size
etc. qui entraînent tous de meilleures performances
PHP :
En PHP pur, vous pouvez créer MySQL Worker où chaque requête est exécutée dans des threads PHP séparés
$sql = new SQLWorker($host, $user, $pass, $db);
$sql->start();
$sql->stack($q1 = new SQLQuery("One long Query"));
$sql->stack($q2 = new SQLQuery("Another long Query"));
$q1->wait();
$q2->wait();
// Do Something Useful
Voici un exemple de travail complet de SQLWorker
2 :analyse du contenu HTML
Si vous connaissez déjà le problème, il est alors plus facile de le résoudre via des boucles d'événements, la file d'attente de tâches ou l'utilisation de Threads.
Travailler sur un document un par un peut être très, très processus lent et douloureux. @ka
une fois piraté en utilisant ajax pour appeler plusieurs requêtes, certains esprits créatifs feraient simplement le processus en utilisant pcntl_fork
mais si vous utilisez windows
alors vous ne pouvez pas profiter de pcntl
Avec pThreads
prenant en charge les systèmes Windows et Unix, vous n'avez pas une telle limitation. Est aussi simple que .. Si vous avez besoin d'analyser 100 documents ? Générer 100 fils ... Simple
Analyse HTML
// Scan my System
$dir = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$dir = new RecursiveIteratorIterator($dir);
// Allowed Extension
$ext = array(
"html",
"htm"
);
// Threads Array
$ts = array();
// Simple Storage
$s = new Sink();
// Start Timer
$time = microtime(true);
$count = 0;
// Parse All HTML
foreach($dir as $html) {
if ($html->isFile() && in_array($html->getExtension(), $ext)) {
$count ++;
$ts[] = new LinkParser("$html", $s);
}
}
// Wait for all Threads to finish
foreach($ts as $t) {
$t->join();
}
// Put The Output
printf("Total Files:\t\t%s \n", number_format($count, 0));
printf("Total Links:\t\t%s \n", number_format($t = count($s), 0));
printf("Finished:\t\t%0.4f sec \n", $tm = microtime(true) - $time);
printf("AvgSpeed:\t\t%0.4f sec per file\n", $tm / $t);
printf("File P/S:\t\t%d file per sec\n", $count / $tm);
printf("Link P/S:\t\t%d links per sec\n", $t / $tm);
Sortie
Total Files: 8,714
Total Links: 105,109
Finished: 108.3460 sec
AvgSpeed: 0.0010 sec per file
File P/S: 80 file per sec
Link P/S: 907 links per sec
Classe utilisée
Sink
class Sink extends Stackable {
public function run() {
}
}
LinkParser
class LinkParser extends Thread {
public function __construct($file, $sink) {
$this->file = $file;
$this->sink = $sink;
$this->start();
}
public function run() {
$dom = new DOMDocument();
@$dom->loadHTML(file_get_contents($this->file));
foreach($dom->getElementsByTagName('a') as $links) {
$this->sink[] = $links->getAttribute('href');
}
}
}
Expérimenter
Essayer d'analyser 8,714
fichiers qui ont 105,109
des liens sans fils et voyez combien de temps cela prendrait.
Meilleure architecture
Générer trop de threads, ce qui n'est pas une chose intelligente à faire en production. Une meilleure approche serait d'utiliser Pooling
. Avoir un pool de définition Travailleurs
puis pile
avec une Task
Amélioration des performances
Très bien, l'exemple ci-dessus peut encore être amélioré. Au lieu d'attendre que le système analyse tous les fichiers dans un seul thread, vous pouvez utiliser plusieurs threads pour analyser mon système à la recherche de fichiers, puis empiler les données sur Workers pour traitement
3 :Mise à jour de l'index de recherche
Cela a été à peu près répondu par la première réponse, mais il y a tellement de façons d'améliorer les performances. Avez-vous déjà envisagé une approche basée sur les événements ?
Présentation de l'événement
@rdlowrey Citation 1 :
@rdlowrey Citation 2 :
Pourquoi ne pas expérimenter avec event-driven
, non-blocking I/O
approche de votre problème. PHP a libevent
pour dynamiser votre application.
Je sais que cette question est tout Multi-Threading
mais si vous avez un peu de temps, vous pouvez regarder ce Réacteur nucléaire écrit en PHP
par @igorw
Enfin
Considération
Je pense que vous devriez envisager d'utiliser Cache
et Job Queue
pour certaines de vos tâches. Vous pouvez facilement avoir un message disant
Document uploaded for processing ..... 5% - Done
Ensuite, faites toutes les tâches qui vous font perdre du temps en arrière-plan. Veuillez consulter Rendre une grande tâche de traitement plus petite pour une étude de cas similaire.
Profilage
Outil de profilage ? Il n'y a pas d'outil de profil unique pour une application Web de Xdebug à Yslow sont tous très utiles. Par exemple. Xdebug n'est pas utile en ce qui concerne les threads car il n'est pas pris en charge
Je n'ai pas de favori