Introduzione
PHP ha il Multi-Threading completo supporto di cui puoi sfruttare appieno in tanti modi. Sono stato in grado di dimostrare questa capacità multi-threading in diversi esempi:
- Come si può utilizzare il multithreading nelle applicazioni PHP
- pcntl esegue lo stesso codice più volte, è richiesta assistenza
- Miglioramento dell'efficienza dello scraper HTML con pcntl_fork()
Una ricerca rapida darebbe risorse aggiuntive.
Categorie
1:query MySQL
MySQL è completamente multi-thread e utilizzerà più CPU, a condizione che il sistema operativo le supporti, massimizzerebbe anche le risorse di sistema se configurato correttamente per le prestazioni.
Un'impostazione tipica in my.ini
che influiscono sulle prestazioni del thread è:
thread_cache_size = 8
thread_cache_size può essere aumentato per migliorare le prestazioni se hai molte nuove connessioni. Normalmente, questo non fornisce un notevole miglioramento delle prestazioni se si dispone di una buona implementazione del thread. Tuttavia, se il tuo server vede centinaia di connessioni al secondo, normalmente dovresti impostare thread_cache_size sufficientemente alto in modo che la maggior parte delle nuove connessioni utilizzi thread memorizzati nella cache
Se stai utilizzando Solaris allora puoi usare
thread_concurrency = 8
thread_concurrency consente alle applicazioni di fornire al sistema di thread un suggerimento sul numero desiderato di thread da eseguire contemporaneamente.
Questa variabile è deprecata a partire da MySQL 5.6.1 e viene rimossa in MySQL 5.7. Dovresti rimuoverlo dai file di configurazione di MySQL ogni volta che lo vedi, a meno che non siano per Solaris 8 o precedenti.
InnoDB: :
Non hai tali limitazioni se stai usando Innod ha il motore di archiviazione perché supporta completamente la concorrenza dei thread
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Puoi anche guardare innodb_read_io_threads
e innodb_write_io_threads
dove l'impostazione predefinita è 4
e può essere aumentato fino a 64
a seconda dell'hardware
Altri:
Altre configurazioni da considerare includono key_buffer_size
, table_open_cache
, sort_buffer_size
ecc. che si traducono in prestazioni migliori
PHP:
In PHP puro puoi creare MySQL Worker in cui ogni query viene eseguita in thread PHP separati
$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
Ecco un esempio di lavoro completo di SQLWorker
2:Analisi del contenuto HTML
Se conosci già il problema, è più facile risolverlo tramite loop di eventi, coda di lavoro o utilizzando i thread.
Lavorare su un documento uno alla volta può essere un molto, molto processo lento e doloroso. @ka
una volta hackerato la via d'uscita usando ajax per chiamare richieste multiple, alcune menti creative avrebbero semplicemente biforcato il processo usando pcntl_fork
ma se stai usando windows
allora non puoi sfruttare pcntl
Con pThreads
supportando entrambi i sistemi Windows e Unix, non hai tale limitazione. È facile come .. Se hai bisogno di analizzare 100 documenti? Genera 100 thread... Semplice
Scansione 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);
Risultato
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 usata
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');
}
}
}
Esperimento
Tentativo di analisi di 8,714
file che hanno 105,109
link senza thread e guarda quanto tempo ci vorrebbe.
Architettura migliore
Generare troppi thread che non è una cosa intelligente da fare In produzione. Un approccio migliore sarebbe usare Pooling
. Avere un pool di define Lavoratori
quindi stack
con un Task
Miglioramento delle prestazioni
Bene, l'esempio sopra può ancora essere migliorato. Invece di attendere che il sistema esegua la scansione di tutti i file in un singolo thread, puoi utilizzare più thread per scansionare il mio sistema alla ricerca di file, quindi impilare i dati in Workers per l'elaborazione
3:aggiornamento dell'indice di ricerca
Questo è stato praticamente risposto dalla prima risposta, ma ci sono così tanti modi per migliorare le prestazioni. Hai mai considerato un approccio basato sugli eventi?
Introduzione all'evento
@rdlowrey Citazione 1:
@rdlowrey Citazione 2:
Perché non provi con event-driven
, non-blocking I/O
approccio al tuo problema. PHP ha libevent
per potenziare la tua applicazione.
So che questa domanda è tutta Multi-Threading
ma se hai un po' di tempo puoi guardare questo Reattore nucleare scritto in PHP
di @igorw
Finalmente
Considerazione
Penso che dovresti considerare di usare Cache
e Job Queue
per alcuni dei tuoi compiti Puoi facilmente avere un messaggio che dice
Document uploaded for processing ..... 5% - Done
Quindi fai tutto il tempo sprecando compiti in background. Si prega di guardare Ridurre un grande lavoro di elaborazione per un caso di studio simile.
Profilazione
Strumento di profilatura? Non esiste uno strumento di profilo unico per un'applicazione web da Xdebug a Yslow sono tutti molto utili. Per esempio. Xdebug non è utile quando si tratta di thread perché non è supportato
Non ho un preferito