Introduktion
PHP har fullständig Multi-Threading stöd som du kan dra full nytta av på så många sätt. Har kunnat demonstrera denna Multi-Threading-förmåga i olika exempel:
- Hur kan man använda multi threading i PHP-applikationer
- pcntl kör samma kod flera gånger, hjälp krävs
- Förbättra HTML-skrapans effektivitet med pcntl_fork()
En snabbsökning skulle ge ytterligare resurser.
Kategorier
1:MySQL-frågor
MySQL är helt flertrådig och kommer att använda flera processorer, förutsatt att operativsystemet stöder dem. Det skulle också maximera systemresurserna om det är korrekt konfigurerat för prestanda.
En typisk inställning i my.ini
som påverkar trådens prestanda är:
thread_cache_size = 8
thread_cache_size kan ökas för att förbättra prestandan om du har många nya anslutningar. Normalt ger detta ingen märkbar prestandaförbättring om du har en bra trådimplementering. Men om din server ser hundratals anslutningar per sekund bör du normalt ställa in thread_cache_size tillräckligt högt så att de flesta nya anslutningar använder cachade trådar
Om du använder Solaris sedan kan du använda
thread_concurrency = 8
thread_concurrency gör det möjligt för applikationer att ge trådsystemet en ledtråd om det önskade antalet trådar som bör köras samtidigt.
Denna variabel är utfasad från och med MySQL 5.6.1 och tas bort i MySQL 5.7. Du bör ta bort detta från MySQL-konfigurationsfilerna när du ser det om de inte är för Solaris 8 eller tidigare.
InnoDB: :
Du har inte sådana begränsningar om du använder Innodb har lagringsmotorn eftersom den fullt ut stöder trådsamtidighet
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Du kan också titta på innodb_read_io_threads
och innodb_write_io_threads
där standard är 4
och det kan ökas till så högt som 64
beroende på hårdvaran
Andra:
Andra konfigurationer att också titta på inkluderar key_buffer_size
, table_open_cache
, sort_buffer_size
etc. vilket ger bättre prestanda
PHP:
I ren PHP kan du skapa MySQL Worker där varje fråga exekveras i separata PHP-trådar
$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
Här är ett fullständigt fungerande exempel på SQLWorker
2:HTML-innehållsanalys
Om du redan känner till problemet gör det det lättare att lösa via händelseloopar, jobbkö eller med hjälp av trådar.
Att arbeta med ett dokument ett i taget kan vara mycket, väldigt långsam, smärtsam process. @ka
en gång hackade sig ut genom att använda ajax för att anropa flera förfrågningar, skulle vissa kreativa hjärnor bara splittra processen med pcntl_fork
men om du använder windows
då kan du inte dra nytta av pcntl
Med pThreads
stöder både Windows och Unix-system, Du har inte en sådan begränsning. Är så enkelt som .. Om du behöver analysera 100 dokument? Skapa 100 trådar ... Enkel
HTML-skanning
// 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);
Utdata
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
Klass använd
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');
}
}
}
Experimentera
Försöker tolka 8,714
filer som har 105,109
länkar utan trådar och se hur lång tid det skulle ta.
Bättre arkitektur
Spawning för många trådar som inte är en smart sak att göra i produktion. Ett bättre tillvägagångssätt skulle vara att använda Pooling
. Ha en pool av definiera arbetare
sedan stack
med en Task
Prestandaförbättring
Okej, exemplet ovan kan fortfarande förbättras. Istället för att vänta på att systemet ska skanna alla filer i en enda tråd kan du använda flera trådar för att skanna mitt system efter filer och sedan stapla data till Workers för bearbetning
3:Uppdatering av sökindex
Detta har i stort sett besvarats av det första svaret, men det finns så många sätt att förbättra prestanda. Har du någonsin övervägt ett evenemangsbaserat tillvägagångssätt?
Introduktion av event
@rdlowrey Citat 1:
@rdlowrey Citat 2:
Varför inte experimentera med event-driven
, non-blocking I/O
förhållningssätt till ditt problem. PHP har libevent
för att ladda upp din ansökan.
Jag vet att den här frågan är Multi-Threading
men om du har lite tid kan du titta på den här Kärnreaktorn skriven i PHP
av @igorw
Äntligen
Övervägande
Jag tycker att du bör överväga att använda Cache
och Job Queue
för några av dina uppgifter. Du kan enkelt få ett meddelande som säger
Document uploaded for processing ..... 5% - Done
Gör sedan hela tiden att slösa uppgifter i bakgrunden. Titta på Göra ett stort bearbetningsjobb mindre för en liknande fallstudie.
Profilering
Profileringsverktyg? Det finns inget enskilt profilverktyg för en webbapplikation från Xdebug till Yslow är alla mycket användbara. T.ex. Xdebug är inte användbart när det kommer till trådar eftersom det inte stöds
Jag har ingen favorit