Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie können Sie Multicore-CPUs in Ihren PHP/MySQL-Anwendungen sinnvoll nutzen?

Einführung

PHP hat volles Multi-Threading Unterstützung, von der Sie in vielerlei Hinsicht profitieren können. Konnten diese Multi-Threading-Fähigkeit in verschiedenen Beispielen demonstrieren:

Eine Schnellsuche würde zusätzliche Ressourcen geben.

Kategorien

1:MySQL-Abfragen

MySQL ist vollständig Multithreading und nutzt mehrere CPUs, vorausgesetzt, das Betriebssystem unterstützt sie. Es würde auch die Systemressourcen maximieren, wenn es für die Leistung richtig konfiguriert ist.

Eine typische Einstellung in der my.ini die die Thread-Leistung beeinflussen, ist :

thread_cache_size = 8

thread_cache_size kann erhöht werden, um die Leistung zu verbessern, wenn Sie viele neue Verbindungen haben. Normalerweise bietet dies keine nennenswerte Leistungsverbesserung, wenn Sie über eine gute Thread-Implementierung verfügen. Wenn Ihr Server jedoch Hunderte von Verbindungen pro Sekunde sieht, sollten Sie thread_cache_size normalerweise hoch genug setzen, damit die meisten neuen Verbindungen zwischengespeicherte Threads verwenden

Wenn Sie Solaris verwenden dann können Sie

verwenden
thread_concurrency = 8 

thread_concurrency ermöglicht es Anwendungen, dem Thread-System einen Hinweis auf die gewünschte Anzahl von Threads zu geben, die gleichzeitig ausgeführt werden sollen.

Diese Variable ist ab MySQL 5.6.1 veraltet und wurde in MySQL 5.7 entfernt. Sie sollten dies immer dann aus den MySQL-Konfigurationsdateien entfernen, wenn Sie es sehen, es sei denn, sie gelten für Solaris 8 oder früher.

InnoDB: :

Sie haben solche Einschränkungen nicht, wenn Sie verwenden Innodb hat die Speicher-Engine, weil sie Thread-Parallelität vollständig unterstützt

innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks

Sie können sich auch innodb_read_io_threads ansehen und innodb_write_io_threads wobei der Standardwert 4 ist und kann auf bis zu 64 erhöht werden abhängig von der Hardware

Andere:

Andere Konfigurationen, die Sie sich ebenfalls ansehen sollten, sind key_buffer_size , table_open_cache , sort_buffer_size usw., die alle zu einer besseren Leistung führen

PHP:

In reinem PHP können Sie MySQL Worker erstellen, in dem jede Abfrage in separaten PHP-Threads ausgeführt wird

$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

Hier ist ein voll funktionsfähiges Beispiel für SQLWorker

2:HTML-Content-Parsing

Wenn Sie das Problem bereits kennen, ist es einfacher, es über Ereignisschleifen, Jobwarteschlangen oder die Verwendung von Threads zu lösen.

Die Arbeit an einem Dokument nach dem anderen kann sehr, sehr sein langsamer, schmerzhafter Prozess. @ka Nachdem er sich mit Ajax heraus gehackt hatte, um mehrere Anfragen aufzurufen, teilten einige kreative Köpfe den Prozess einfach mit pcntl_fork aber wenn Sie windows verwenden dann können Sie pcntl nicht nutzen

Mit pThreads unterstützt sowohl Windows- als auch Unix-Systeme, Sie haben keine solche Einschränkung. Ist so einfach wie .. Wenn Sie 100 Dokumente analysieren müssen? 100 Threads erzeugen ... Einfach

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

Ausgabe

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

Verwendete Klasse

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

Experimentieren

Versuch, 8,714 zu parsen Dateien mit 105,109 Links ohne Threads und sehen, wie lange es dauern würde.

Bessere Architektur

Zu viele Threads erzeugen, was in der Produktion nicht klug ist. Ein besserer Ansatz wäre die Verwendung von Pooling . Haben Sie einen Pool von definierten Arbeitern dann stack mit einer Task

Leistungsverbesserung

Gut, das obige Beispiel kann noch verbessert werden. Anstatt darauf zu warten, dass das System alle Dateien in einem einzigen Thread scannt, können Sie mehrere Threads verwenden, um mein System nach Dateien zu scannen, und die Daten dann zur Verarbeitung in Workers stapeln

3:Aktualisierung des Suchindex

Dies wurde mit der ersten Antwort ziemlich genau beantwortet, aber es gibt so viele Möglichkeiten zur Leistungsverbesserung. Haben Sie jemals einen ereignisbasierten Ansatz in Erwägung gezogen?

Einführungsveranstaltung

@rdlowrey Zitat 1:

@rdlowrey Zitat 2:

Warum experimentieren Sie nicht mit event-driven , non-blocking I/O Herangehensweise an dein Problem. PHP hat libevent um Ihre Bewerbung aufzuladen.

Ich weiß, dass diese Frage alles Multi-Threading ist aber wenn Sie etwas Zeit haben, können Sie sich diesen Nuclear Reactor in PHP geschrieben ansehen von @igorw

Endlich

Gegenleistung

Ich denke, Sie sollten die Verwendung von Cache in Betracht ziehen und Job Queue für einige Ihrer Aufgaben. Sie können ganz einfach eine Nachricht mit folgendem Inhalt haben:

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

Erledige dann all die zeitraubenden Aufgaben im Hintergrund. Bitte schauen Sie sich Einen großen Verarbeitungsauftrag verkleinern an für eine ähnliche Fallstudie.

Profilerstellung

Profiling-Tool? Es gibt kein einzelnes Profiltool für eine Webanwendung von Xdebug zu Yslow sind alle sehr nützlich. Z.B. Xdebug ist nicht nützlich, wenn es um Threads geht, da es nicht unterstützt wird

Ich habe keinen Favoriten