sql >> Databasteknik >  >> RDS >> Mysql

Hur utnyttjar du flerkärniga processorer i dina PHP/MySQL-applikationer?

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:

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



  1. Hur lägger man till en where-klausul i en MySQL Insert-sats?

  2. PostgreSQL multi INSERT...RETURNERAR med flera kolumner

  3. SQL välj endast rader med maxvärde på en kolumn

  4. SQL Server Infoga Exempel