sql >> Databáze >  >> RDS >> Mysql

Jak dobře využíváte vícejádrové procesory ve vašich aplikacích PHP/MySQL?

Úvod

PHP má plné Multi-Threading podporu, kterou můžete naplno využít mnoha způsoby. Byli schopni demonstrovat tuto schopnost Multi-Threading na různých příkladech:

rychlé vyhledávání by poskytlo další zdroje.

Kategorie

1:Dotazy MySQL

MySQL je plně funkční vícevláknové a bude využívat více CPU za předpokladu, že je operační systém podporuje. Také by to maximalizovalo systémové prostředky, pokud by byly správně nakonfigurovány pro výkon.

Typické nastavení v my.ini které ovlivňují výkon vlákna je:

thread_cache_size = 8

thread_cache_size lze zvýšit pro zlepšení výkonu, pokud máte mnoho nových připojení. Pokud máte dobrou implementaci vlákna, toto obvykle neposkytuje výrazné zlepšení výkonu. Pokud však váš server vidí stovky připojení za sekundu, měli byste normálně nastavit thread_cache_size dostatečně vysoko, aby většina nových připojení používala vlákna uložená v mezipaměti

Pokud používáte Solaris pak můžete použít

thread_concurrency = 8 

thread_concurrency umožňuje aplikacím poskytnout systému vláken nápovědu o požadovaném počtu vláken, která by měla být spuštěna současně.

Tato proměnná je zastaralá od MySQL 5.6.1 a je odstraněna v MySQL 5.7. Měli byste to odstranit z konfiguračních souborů MySQL, kdykoli to uvidíte, pokud nejsou pro Solaris 8 nebo starší.

InnoDB: :

Tato omezení nemáte, pokud používáte Innodb má modul úložiště, protože plně podporuje souběžnost vláken

innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks

Můžete se také podívat na innodb_read_io_threads a innodb_write_io_threads kde výchozí je 4 a lze jej zvýšit až na 64 v závislosti na hardwaru

Ostatní:

Mezi další konfigurace, na které se také můžete podívat, patří key_buffer_size , table_open_cache , sort_buffer_size atd., jejichž výsledkem je lepší výkon

PHP:

V čistém PHP můžete vytvořit MySQL Worker, kde se každý dotaz provádí v samostatných PHP vláknech

$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

Zde je úplný pracovní příklad SQLWorker

2:Analýza obsahu HTML

Pokud již problém znáte, je snazší jej vyřešit pomocí smyček událostí, fronty úloh nebo pomocí vláken.

Práce na jednom dokumentu jeden po druhém může být velmi, velmi pomalý, bolestivý proces. @ka jakmile se jednou naboural pomocí ajaxu k volání vícenásobného požadavku, někteří kreativní myslitelé by proces jednoduše rozvětvovali pomocí pcntl_fork ale pokud používáte windows pak nemůžete využít výhod pcntl

Pomocí pThreads podporující jak Windows, tak Unix systémy, nemáte takové omezení. Je to tak snadné jako .. Pokud potřebujete analyzovat 100 dokumentů? Vytvořit 100 vláken ... Jednoduché

Skenování 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);

Výstup

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

Použitá třída

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');
        }
    }
}

Experiment

Pokus o analýzu 8,714 soubory, které mají 105,109 odkazy bez vláken a uvidíte, jak dlouho by to trvalo.

Lepší architektura

Vytváření příliš mnoha vláken, což není chytrá věc ve výrobě. Lepším přístupem by bylo použít Pooling . Mít soubor definovaných pracovníků pak skládat s Task

Zlepšení výkonu

Dobře, výše uvedený příklad lze ještě vylepšit. Namísto čekání, až systém prohledá všechny soubory v jednom vláknu, můžete použít více vláken k prohledání souborů v mém systému a poté naskládat data do Workers ke zpracování

3:Aktualizace vyhledávacího indexu

To bylo do značné míry zodpovězeno první odpovědí, ale existuje mnoho způsobů, jak zlepšit výkon. Uvažovali jste někdy o přístupu založeném na událostech?

Představujeme událost

@rdlowrey Citace 1:

@rdlowrey Citace 2:

Proč nezkusit experimentovat s event-driven , non-blocking I/O přístup k vašemu problému. PHP má libevent pro nabití vaší aplikace.

Vím, že tato otázka je celá Multi-Threading ale pokud máte trochu času, můžete se podívat na tento nukleární reaktor napsaný v PHP od @igorw

Konečně

Zvažování

Myslím, že byste měli zvážit použití Cache a Job Queue pro některé z vašich úkolů. Můžete snadno dostat zprávu s nápisem

Document uploaded for processing ..... 5% - Done   

Pak provádějte všechny úkoly plýtvání časem na pozadí. Podívejte se prosím na Zmenšení velké úlohy zpracování pro podobnou případovou studii.

Profilování

Nástroj pro profilování? Pro webovou aplikaci z Xdebug neexistuje jediný profilový nástroj na Yslow všechny jsou velmi užitečné. Např. Xdebug není užitečný, pokud jde o vlákna, protože není podporován

Nemám oblíbené



  1. Vyberte N předchozích a M dalších položek kolem aktuálního ID položky

  2. MySQL dotaz k získání nejprodávanějších produktů

  3. Nastavte znakovou sadu a řazení sloupce v MariaDB

  4. Přidejte Ordinal Indicator k datu v Oracle