Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak dobrze wykorzystujesz wielordzeniowe procesory w swoich aplikacjach PHP/MySQL?

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:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. GRUPUJ WEDŁUG MAKSYMALNEJ DATY

  2. MySQL zwraca pierwszy i ostatni rekord dla kolejnych identycznych wyników

  3. Jak działa funkcja LOWER() w MySQL

  4. Jakie jest najlepsze kodowanie znaków dla języka japońskiego dla wyświetlania DB, php i html?

  5. Nazwa schematu MySQL z myślnikiem nie pozwala mi na wykonanie zapytania wiersza poleceń