sql >> Database teknologi >  >> RDS >> Mysql

Hvordan gør du god brug af multicore CPU'er i dine PHP/MySQL-applikationer?

Introduktion

PHP har fuld Multi-Threading støtte, som du kan drage fuld fordel af på så mange måder. Har været i stand til at demonstrere denne Multi-Threading-evne i forskellige eksempler:

En hurtig søgning ville give yderligere ressourcer.

Kategorier

1:MySQL-forespørgsler

MySQL er fuldt ud flertrådet og vil gøre brug af flere CPU'er, forudsat at operativsystemet understøtter dem. Det vil også maksimere systemressourcerne, hvis det er konfigureret korrekt til ydeevne.

En typisk indstilling i my.ini der påvirker trådens ydeevne er:

thread_cache_size = 8

thread_cache_size kan øges for at forbedre ydeevnen, hvis du har mange nye forbindelser. Normalt giver dette ikke en nævneværdig forbedring af ydeevnen, hvis du har en god trådimplementering. Men hvis din server ser hundredvis af forbindelser i sekundet, bør du normalt indstille thread_cache_size højt nok, så de fleste nye forbindelser bruger cachelagrede tråde

Hvis du bruger Solaris så kan du bruge

thread_concurrency = 8 

thread_concurrency gør det muligt for applikationer at give trådsystemet et hint om det ønskede antal tråde, der skal køres på samme tid.

Denne variabel er forældet fra og med MySQL 5.6.1 og fjernes i MySQL 5.7. Du bør fjerne dette fra MySQL-konfigurationsfiler, når du ser det, medmindre de er til Solaris 8 eller tidligere.

InnoDB: :

Du har ikke sådanne begrænsninger, hvis du bruger Innodb har lagringsmotoren, fordi den fuldt ud understøtter trådens samtidighed

innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks

Du kan også se på innodb_read_io_threads og innodb_write_io_threads hvor standarden er 4 og det kan øges til så højt som 64 afhængigt af hardwaren

Andre:

Andre konfigurationer at også se på inkluderer key_buffer_size , table_open_cache , sort_buffer_size osv. hvilket kalder alle resulterer i bedre ydeevne

PHP:

I ren PHP kan du oprette MySQL Worker, hvor hver forespørgsel udføres i separate PHP-tråde

$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

Her er et komplet eksempel på SQLWorker

2:Parsing af HTML-indhold

Hvis du allerede kender problemet, gør det det nemmere at løse via hændelsesløkker, jobkø eller ved at bruge tråde.

At arbejde på ét dokument ad gangen kan være meget, meget langsom, smertefuld proces. @ka engang hacket sig ud ved at bruge ajax til at kalde flere anmodninger, ville nogle kreative hjerner bare forgrene processen ved at bruge pcntl_fork men hvis du bruger windows så kan du ikke drage fordel af pcntl

Med pThreads understøtter både Windows og Unix-systemer. Du har ikke en sådan begrænsning. Er så let som .. Hvis du har brug for at parse 100 dokument? Skab 100 tråde ... Simpelt

HTML-scanning

// 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);

Output

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 brugt

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

Eksperiment

Prøver at parse 8,714 filer, der har 105,109 links uden tråde og se, hvor lang tid det ville tage.

Bedre arkitektur

At gyde for mange tråde, hvilket ikke er en smart ting at gøre i produktionen. En bedre metode ville være at bruge pooling . Har en pulje af definere arbejdere derefter stak med en Task

Ydeevneforbedring

Fint, eksemplet ovenfor kan stadig forbedres. I stedet for at vente på, at systemet scanner alle filer i en enkelt tråd, kan du bruge flere tråde til at scanne mit system for filer og derefter stable dataene til Workers til behandling

3:Opdatering af søgeindeks

Dette er stort set blevet besvaret af det første svar, men der er så mange måder at forbedre ydeevnen på. Har du nogensinde overvejet en begivenhedsbaseret tilgang?

Introduktion til begivenhed

@rdlowrey Citat 1:

@rdlowrey Citat 2:

Hvorfor eksperimenterer du ikke med event-driven , non-blocking I/O tilgang til dit problem. PHP har libevent for at overlade din ansøgning.

Jeg ved, at dette spørgsmål udelukkende er Multi-Threading men hvis du har lidt tid, kan du se denne Atomreaktor skrevet i PHP af @igorw

Endelig

Overvejelse

Jeg synes, du bør overveje at bruge Cache og Job Queue til nogle af dine opgaver. Du kan nemt få en besked, der siger

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

Så lav hele tiden spildende opgaver i baggrunden. Se venligst Gør et stort behandlingsjob mindre til et lignende casestudie.

Profilering

Profileringsværktøj? Der er ikke noget enkelt profilværktøj til en webapplikation fra Xdebug til Yslow er alle meget nyttige. For eksempel. Xdebug er ikke nyttigt, når det kommer til tråde, fordi det ikke understøttes

Jeg har ikke en favorit



  1. Fejl ved genstart af Openshift MySQL-patron

  2. Alt du behøver at vide om databasenormalisering

  3. Er der en mysql JDBC, der respekterer fetchSize?

  4. MySql.Data.MySqlClient.Replication.ReplicationManager kaster en System.TypeInitializationException