Inleiding
PHP heeft volledige Multi-Threading ondersteuning waar u op zoveel manieren optimaal gebruik van kunt maken. Heb dit Multi-Threading-vermogen in verschillende voorbeelden kunnen demonstreren:
- Hoe kan men multithreading gebruiken in PHP-applicaties
- pcntl voert dezelfde code meerdere keren uit, hulp vereist
- De efficiëntie van HTML-scraper verbeteren met pcntl_fork()
Een snel zoeken zou extra middelen geven.
Categorieën
1:MySQL-query's
MySQL is volledig multi-threaded en zal gebruik maken van meerdere CPU's, op voorwaarde dat het besturingssysteem ze ondersteunt. Het zou ook de systeembronnen maximaliseren als het correct is geconfigureerd voor prestaties.
Een typische instelling in de my.ini
die van invloed zijn op de draadprestaties zijn:
thread_cache_size = 8
thread_cache_size kan worden verhoogd om de prestaties te verbeteren als u veel nieuwe verbindingen heeft. Normaal gesproken levert dit geen noemenswaardige prestatieverbetering op als je een goede thread-implementatie hebt. Als uw server echter honderden verbindingen per seconde ziet, moet u thread_cache_size normaal gesproken hoog genoeg instellen zodat de meeste nieuwe verbindingen gecachte threads gebruiken
Als u Solaris gebruikt dan kun je
. gebruikenthread_concurrency = 8
thread_concurrency stelt toepassingen in staat om het threadsysteem een hint te geven over het gewenste aantal threads dat tegelijkertijd moet worden uitgevoerd.
Deze variabele is verouderd vanaf MySQL 5.6.1 en wordt verwijderd in MySQL 5.7. U moet dit verwijderen uit MySQL-configuratiebestanden wanneer u het ziet, tenzij ze voor Solaris 8 of eerder zijn.
InnoDB: :
U hebt dergelijke beperkingen niet als u gebruikt Innodb heeft de opslag-engine omdat deze thread-concurrency volledig ondersteunt
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Je kunt ook kijken op innodb_read_io_threads
en innodb_write_io_threads
waarbij de standaard 4
. is en het kan worden verhoogd tot wel 64
afhankelijk van de hardware
Overige:
Andere configuraties om ook naar te kijken zijn key_buffer_size
, table_open_cache
, sort_buffer_size
enz. die allemaal resulteren in betere prestaties
PHP:
In pure PHP kun je MySQL Worker maken waarbij elke query wordt uitgevoerd in afzonderlijke PHP-threads
$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
Hier is een volledig werkend voorbeeld van SQLWorker
2:HTML-inhoud ontleden
Als u het probleem al kent, is het gemakkelijker op te lossen via gebeurtenislussen, taakwachtrij of het gebruik van threads.
Eén voor één aan één document werken kan een heel, heel . zijn langzaam, pijnlijk proces. @ka
eenmaal gehackt met ajax om meerdere verzoeken te bellen, zouden sommige creatieve geesten het proces gewoon splitsen met behulp van pcntl_fork
maar als je windows
gebruikt dan kunt u geen gebruik maken van pcntl
Met pThreads
die zowel Windows als Unix-systemen ondersteunt, heeft u niet zo'n beperking. Is zo eenvoudig als .. Als u 100 documenten moet ontleden? Spawn 100 Threads ... Eenvoudig
HTML-scannen
// 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);
Uitvoer
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 gebruikt
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');
}
}
}
Experimenteren
Probeert 8,714
te ontleden bestanden met 105,109
links zonder discussielijnen en kijk hoe lang het zou duren.
Betere architectuur
Te veel threads voortbrengen, wat niet slim is om te doen in productie. Een betere benadering zou zijn om Pooling
te gebruiken . Zorg voor een pool van definiëren Werknemers
dan stapelen
met een Task
Prestatieverbetering
Prima, bovenstaand voorbeeld kan nog verbeterd worden. In plaats van te wachten tot het systeem alle bestanden in een enkele thread scant, kunt u meerdere threads gebruiken om mijn systeem op bestanden te scannen en de gegevens vervolgens naar Workers te stapelen voor verwerking
3:Update zoekindex
Dit is vrijwel beantwoord door het eerste antwoord, maar er zijn zoveel manieren om de prestaties te verbeteren. Heb je ooit een Event-based aanpak overwogen?
Introductie van evenement
@rdlowrey Citaat 1:
@rdlowrey Citaat 2:
Waarom experimenteer je niet met event-driven
, non-blocking I/O
benadering van uw probleem. PHP heeft libevent
om uw toepassing te boosten.
Ik weet dat deze vraag allemaal Multi-Threading
is maar als je wat tijd hebt, kun je dit bekijken Kernreactor geschreven in PHP
door @igorw
Eindelijk
Overweging
Ik denk dat je moet overwegen om Cache
te gebruiken en Job Queue
voor een aantal van je taken. U kunt gemakkelijk een bericht krijgen met de tekst
Document uploaded for processing ..... 5% - Done
Verspil vervolgens de hele tijd aan het verspillen van taken op de achtergrond. Kijk op Een grote verwerkingstaak kleiner maken voor een vergelijkbare case study.
Profilering
Profileringstool? Er is geen enkele profieltool voor een webtoepassing van Xdebug naar Yslow zijn allemaal erg handig. bijv. Xdebug is niet handig als het gaat om threads omdat het niet wordt ondersteund
Ik heb geen favoriet