Wprowadzenie
PHP ma pełne Wielowątkowość wsparcie, z którego możesz w pełni korzystać na wiele sposobów. Udało mi się zademonstrować tę umiejętność wielowątkowości na różnych przykładach:
- Jak używać wielowątkowości w aplikacjach PHP
- pcntl uruchamia ten sam kod kilka razy, wymagana pomoc
- Poprawa wydajności skrobaka HTML z pcntl_fork()
szybkie wyszukiwanie dałoby dodatkowe zasoby.
Kategorie
1:Zapytania MySQL
MySQL jest w pełni wielowątkowy i będzie korzystać z wielu procesorów, pod warunkiem, że system operacyjny je obsługuje. Zwiększyłby również zasoby systemowe, jeśli został odpowiednio skonfigurowany pod kątem wydajności.
Typowe ustawienie w my.ini
które wpływają na wydajność wątku to:
thread_cache_size = 8
thread_cache_size można zwiększyć, aby poprawić wydajność, jeśli masz dużo nowych połączeń. Zwykle nie zapewnia to znaczącej poprawy wydajności, jeśli masz dobrą implementację wątku. Jeśli jednak twój serwer widzi setki połączeń na sekundę, powinieneś normalnie ustawić wartość thread_cache_size na tyle, aby większość nowych połączeń korzystała z buforowanych wątków
Jeśli używasz Solarisa wtedy możesz użyć
thread_concurrency = 8
thread_concurrency umożliwia aplikacjom przekazanie systemowi wątków wskazówki o pożądanej liczbie wątków, które powinny być uruchomione w tym samym czasie.
Ta zmienna jest przestarzała w MySQL 5.6.1 i usunięta w MySQL 5.7. Powinieneś usunąć to z plików konfiguracyjnych MySQL za każdym razem, gdy go zobaczysz, chyba że są one przeznaczone dla systemu Solaris 8 lub wcześniejszego.
InnoDB: :
Nie masz takich ograniczeń, jeśli używasz Innodb ma silnik pamięci masowej, ponieważ w pełni obsługuje współbieżność wątków
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Możesz także spojrzeć na innodb_read_io_threads
i innodb_write_io_threads
gdzie wartość domyślna to 4
i można go zwiększyć do nawet 64
w zależności od sprzętu
Inne:
Inne konfiguracje, na które również należy spojrzeć, to key_buffer_size
, table_open_cache
, sort_buffer_size
itp., które wszystkie wywołania zapewniają lepszą wydajność
PHP:
W czystym PHP możesz utworzyć MySQL Worker, w którym każde zapytanie jest wykonywane w osobnych wątkach PHP
$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
Oto pełny przykład działania SQLWorker
2:Analiza treści HTML
Jeśli znasz już problem, możesz go łatwiej rozwiązać za pomocą pętli zdarzeń, kolejki zadań lub wątków.
Praca nad jednym dokumentem pojedynczo może być bardzo, bardzo powolny, bolesny proces. @ka
kiedyś włamał się za pomocą ajax do wywoływania wielu żądań, niektóre kreatywne umysły po prostu rozwidlałyby proces za pomocą pcntl_widelec
ale jeśli używasz windows
wtedy nie możesz skorzystać z pcntl
Z pThreads
obsługujące zarówno systemy Windows jak i Unix, nie masz takiego ograniczenia. Czy tak proste jak .. Jeśli potrzebujesz przeanalizować 100 dokumentów? Spawn 100 wątków ... Proste
Skanowanie 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);
Wyjście
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
Używana klasa
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');
}
}
}
Eksperyment
Próbuję parsować 8,714
pliki, które mają 105,109
linki bez wątków i zobacz, jak długo to zajmie.
Lepsza architektura
Tworzenie zbyt wielu wątków, co nie jest mądrym posunięciem w produkcji. Lepszym podejściem byłoby użycie Połączenie
. Miej pulę zdefiniowanych Pracowników
następnie stos
z Task
Poprawa wydajności
Dobrze, powyższy przykład można jeszcze poprawić. Zamiast czekać, aż system przeskanuje wszystkie pliki w jednym wątku, możesz użyć wielu wątków do przeskanowania mojego systemu w poszukiwaniu plików, a następnie ułożyć dane do pracowników w celu przetworzenia
3:Aktualizacja indeksu wyszukiwania
Odpowiedzi na to w dużej mierze odpowiedziała pierwsza odpowiedź, ale jest tak wiele sposobów na poprawę wydajności. Czy kiedykolwiek zastanawiałeś się nad podejściem opartym na wydarzeniu?
Przedstawiamy wydarzenie
@rdlowrey Cytat 1:
@rdlowrey Cytat 2:
Dlaczego nie poeksperymentujesz z event-driven
, non-blocking I/O
podejście do Twojego problemu. PHP ma libevent
doładowania aplikacji.
Wiem, że to pytanie dotyczy tylko Multi-Threading
ale jeśli masz trochę czasu, możesz spojrzeć na ten Reaktor jądrowy napisany w PHP
autor:@igorw
Wreszcie
Rozważanie
Myślę, że powinieneś rozważyć użycie Cache
i Job Queue
dla niektórych Twoich zadań. Możesz łatwo otrzymać wiadomość mówiącą
Document uploaded for processing ..... 5% - Done
Następnie cały czas marnuj zadania w tle. Proszę spojrzeć na Zmniejszanie dużego zadania przetwarzania dla podobnego studium przypadku.
Profilowanie
Narzędzie do profilowania? Nie ma jednego narzędzia profilu dla aplikacji internetowej od Xdebug do Yslow są bardzo przydatne. Np. Xdebug nie jest przydatny w przypadku wątków, ponieważ nie jest obsługiwany
Nie mam ulubionego