Introduktion
PHP har fuld Multi-Threading støtte, som du kan drage fuld fordel af på så mange måder. Har været i stand til at demonstrere denne Multi-Threading-evne i forskellige eksempler:
- Hvordan kan man bruge multi-threading i PHP-applikationer
- pcntl kører den samme kode flere gange, hjælp påkrævet
- Forbedring af HTML-skraberens effektivitet med pcntl_fork()
En hurtig søgning ville give yderligere ressourcer.
Kategorier
1:MySQL-forespørgsler
MySQL er fuldt ud flertrådet og vil gøre brug af flere CPU'er, forudsat at operativsystemet understøtter dem. Det vil også maksimere systemressourcerne, hvis det er konfigureret korrekt til ydeevne.
En typisk indstilling i my.ini
der påvirker trådens ydeevne er:
thread_cache_size = 8
thread_cache_size kan øges for at forbedre ydeevnen, hvis du har mange nye forbindelser. Normalt giver dette ikke en nævneværdig forbedring af ydeevnen, hvis du har en god trådimplementering. Men hvis din server ser hundredvis af forbindelser i sekundet, bør du normalt indstille thread_cache_size højt nok, så de fleste nye forbindelser bruger cachelagrede tråde
Hvis du bruger Solaris så kan du bruge
thread_concurrency = 8
thread_concurrency gør det muligt for applikationer at give trådsystemet et hint om det ønskede antal tråde, der skal køres på samme tid.
Denne variabel er forældet fra og med MySQL 5.6.1 og fjernes i MySQL 5.7. Du bør fjerne dette fra MySQL-konfigurationsfiler, når du ser det, medmindre de er til Solaris 8 eller tidligere.
InnoDB: :
Du har ikke sådanne begrænsninger, hvis du bruger Innodb har lagringsmotoren, fordi den fuldt ud understøtter trådens samtidighed
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Du kan også se på innodb_read_io_threads
og innodb_write_io_threads
hvor standarden er 4
og det kan øges til så højt som 64
afhængigt af hardwaren
Andre:
Andre konfigurationer at også se på inkluderer key_buffer_size
, table_open_cache
, sort_buffer_size
osv. hvilket kalder alle resulterer i bedre ydeevne
PHP:
I ren PHP kan du oprette MySQL Worker, hvor hver forespørgsel udføres i separate PHP-tråde
$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
Her er et komplet eksempel på SQLWorker
2:Parsing af HTML-indhold
Hvis du allerede kender problemet, gør det det nemmere at løse via hændelsesløkker, jobkø eller ved at bruge tråde.
At arbejde på ét dokument ad gangen kan være meget, meget langsom, smertefuld proces. @ka
engang hacket sig ud ved at bruge ajax til at kalde flere anmodninger, ville nogle kreative hjerner bare forgrene processen ved at bruge pcntl_fork
men hvis du bruger windows
så kan du ikke drage fordel af pcntl
Med pThreads
understøtter både Windows og Unix-systemer. Du har ikke en sådan begrænsning. Er så let som .. Hvis du har brug for at parse 100 dokument? Skab 100 tråde ... Simpelt
HTML-scanning
// 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);
Output
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
Klasse brugt
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');
}
}
}
Eksperiment
Prøver at parse 8,714
filer, der har 105,109
links uden tråde og se, hvor lang tid det ville tage.
Bedre arkitektur
At gyde for mange tråde, hvilket ikke er en smart ting at gøre i produktionen. En bedre metode ville være at bruge pooling
. Har en pulje af definere arbejdere
derefter stak
med en Task
Ydeevneforbedring
Fint, eksemplet ovenfor kan stadig forbedres. I stedet for at vente på, at systemet scanner alle filer i en enkelt tråd, kan du bruge flere tråde til at scanne mit system for filer og derefter stable dataene til Workers til behandling
3:Opdatering af søgeindeks
Dette er stort set blevet besvaret af det første svar, men der er så mange måder at forbedre ydeevnen på. Har du nogensinde overvejet en begivenhedsbaseret tilgang?
Introduktion til begivenhed
@rdlowrey Citat 1:
@rdlowrey Citat 2:
Hvorfor eksperimenterer du ikke med event-driven
, non-blocking I/O
tilgang til dit problem. PHP har libevent
for at overlade din ansøgning.
Jeg ved, at dette spørgsmål udelukkende er Multi-Threading
men hvis du har lidt tid, kan du se denne Atomreaktor skrevet i PHP
af @igorw
Endelig
Overvejelse
Jeg synes, du bør overveje at bruge Cache
og Job Queue
til nogle af dine opgaver. Du kan nemt få en besked, der siger
Document uploaded for processing ..... 5% - Done
Så lav hele tiden spildende opgaver i baggrunden. Se venligst Gør et stort behandlingsjob mindre til et lignende casestudie.
Profilering
Profileringsværktøj? Der er ikke noget enkelt profilværktøj til en webapplikation fra Xdebug til Yslow er alle meget nyttige. For eksempel. Xdebug er ikke nyttigt, når det kommer til tråde, fordi det ikke understøttes
Jeg har ikke en favorit