sql >> Database >  >> RDS >> Mysql

Hoe maak je goed gebruik van multicore CPU's in je PHP/MySQL-applicaties?

Inleiding

PHP heeft volledige Multi-Threading ondersteuning waar u op zoveel manieren optimaal gebruik van kunt maken. Heb dit Multi-Threading-vermogen in verschillende voorbeelden kunnen demonstreren:

Een snel zoeken zou extra middelen geven.

Categorieën

1:MySQL-query's

MySQL is volledig multi-threaded en zal gebruik maken van meerdere CPU's, op voorwaarde dat het besturingssysteem ze ondersteunt. Het zou ook de systeembronnen maximaliseren als het correct is geconfigureerd voor prestaties.

Een typische instelling in de my.ini die van invloed zijn op de draadprestaties zijn:

thread_cache_size = 8

thread_cache_size kan worden verhoogd om de prestaties te verbeteren als u veel nieuwe verbindingen heeft. Normaal gesproken levert dit geen noemenswaardige prestatieverbetering op als je een goede thread-implementatie hebt. Als uw server echter honderden verbindingen per seconde ziet, moet u thread_cache_size normaal gesproken hoog genoeg instellen zodat de meeste nieuwe verbindingen gecachte threads gebruiken

Als u Solaris gebruikt dan kun je

. gebruiken
thread_concurrency = 8 

thread_concurrency stelt toepassingen in staat om het threadsysteem een ​​hint te geven over het gewenste aantal threads dat tegelijkertijd moet worden uitgevoerd.

Deze variabele is verouderd vanaf MySQL 5.6.1 en wordt verwijderd in MySQL 5.7. U moet dit verwijderen uit MySQL-configuratiebestanden wanneer u het ziet, tenzij ze voor Solaris 8 of eerder zijn.

InnoDB: :

U hebt dergelijke beperkingen niet als u gebruikt Innodb heeft de opslag-engine omdat deze thread-concurrency volledig ondersteunt

innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks

Je kunt ook kijken op innodb_read_io_threads en innodb_write_io_threads waarbij de standaard 4 . is en het kan worden verhoogd tot wel 64 afhankelijk van de hardware

Overige:

Andere configuraties om ook naar te kijken zijn key_buffer_size , table_open_cache , sort_buffer_size enz. die allemaal resulteren in betere prestaties

PHP:

In pure PHP kun je MySQL Worker maken waarbij elke query wordt uitgevoerd in afzonderlijke PHP-threads

$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 is een volledig werkend voorbeeld van SQLWorker

2:HTML-inhoud ontleden

Als u het probleem al kent, is het gemakkelijker op te lossen via gebeurtenislussen, taakwachtrij of het gebruik van threads.

Eén voor één aan één document werken kan een heel, heel . zijn langzaam, pijnlijk proces. @ka eenmaal gehackt met ajax om meerdere verzoeken te bellen, zouden sommige creatieve geesten het proces gewoon splitsen met behulp van pcntl_fork maar als je windows gebruikt dan kunt u geen gebruik maken van pcntl

Met pThreads die zowel Windows als Unix-systemen ondersteunt, heeft u niet zo'n beperking. Is zo eenvoudig als .. Als u 100 documenten moet ontleden? Spawn 100 Threads ... Eenvoudig

HTML-scannen

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

Uitvoer

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 gebruikt

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

Experimenteren

Probeert 8,714 te ontleden bestanden met 105,109 links zonder discussielijnen en kijk hoe lang het zou duren.

Betere architectuur

Te veel threads voortbrengen, wat niet slim is om te doen in productie. Een betere benadering zou zijn om Pooling te gebruiken . Zorg voor een pool van definiëren Werknemers dan stapelen met een Task

Prestatieverbetering

Prima, bovenstaand voorbeeld kan nog verbeterd worden. In plaats van te wachten tot het systeem alle bestanden in een enkele thread scant, kunt u meerdere threads gebruiken om mijn systeem op bestanden te scannen en de gegevens vervolgens naar Workers te stapelen voor verwerking

3:Update zoekindex

Dit is vrijwel beantwoord door het eerste antwoord, maar er zijn zoveel manieren om de prestaties te verbeteren. Heb je ooit een Event-based aanpak overwogen?

Introductie van evenement

@rdlowrey Citaat 1:

@rdlowrey Citaat 2:

Waarom experimenteer je niet met event-driven , non-blocking I/O benadering van uw probleem. PHP heeft libevent om uw toepassing te boosten.

Ik weet dat deze vraag allemaal Multi-Threading is maar als je wat tijd hebt, kun je dit bekijken Kernreactor geschreven in PHP door @igorw

Eindelijk

Overweging

Ik denk dat je moet overwegen om Cache te gebruiken en Job Queue voor een aantal van je taken. U kunt gemakkelijk een bericht krijgen met de tekst

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

Verspil vervolgens de hele tijd aan het verspillen van taken op de achtergrond. Kijk op Een grote verwerkingstaak kleiner maken voor een vergelijkbare case study.

Profilering

Profileringstool? Er is geen enkele profieltool voor een webtoepassing van Xdebug naar Yslow zijn allemaal erg handig. bijv. Xdebug is niet handig als het gaat om threads omdat het niet wordt ondersteund

Ik heb geen favoriet



  1. SQL alles selecteren als parameter null is, anders specifiek item retourneren

  2. MySQL-tabel met AUTO_INCREMENT primaire id geeft het nummer niet vrij na een rollback

  3. Hekaton met een twist:In-memory TVP's – Deel 1

  4. Wat is het verschil tussen de functies RANK() en DENSE_RANK() in Oracle?