Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como você faz bom uso de CPUs multicore em seus aplicativos PHP/MySQL?

Introdução


O PHP tem Multi-Threading completo suporte que você pode aproveitar ao máximo de muitas maneiras. Conseguimos demonstrar essa capacidade de Multi-Threading em diferentes exemplos:

Uma pesquisa rápida daria recursos adicionais.

Categorias

1:consultas MySQL


O MySQL é totalmente multi-thread e fará uso de várias CPUs, desde que o sistema operacional as suporte. Também maximizaria os recursos do sistema se configurado corretamente para desempenho.

Uma configuração típica no my.ini que afetam o desempenho do thread é:
thread_cache_size = 8

thread_cache_size pode ser aumentado para melhorar o desempenho se você tiver muitas novas conexões. Normalmente, isso não fornece uma melhoria de desempenho notável se você tiver uma boa implementação de thread. No entanto, se o seu servidor vê centenas de conexões por segundo, você normalmente deve definir thread_cache_size alto o suficiente para que a maioria das novas conexões use threads em cache

Se você estiver usando o Solaris então você pode usar
thread_concurrency = 8 

thread_concurrency permite que os aplicativos forneçam ao sistema de threads uma dica sobre o número desejado de threads que devem ser executados ao mesmo tempo.

Esta variável está obsoleta a partir do MySQL 5.6.1 e foi removida no MySQL 5.7. Você deve removê-lo dos arquivos de configuração do MySQL sempre que o vir, a menos que sejam para Solaris 8 ou anterior.

InnoDB: :

Você não tem tais limitações se estiver usando Innodb tem o mecanismo de armazenamento porque suporta totalmente a simultaneidade de threads
innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks

Você também pode ver innodb_read_io_threads e innodb_write_io_threads onde o padrão é 4 e pode ser aumentado para até 64 dependendo do hardware

Outros:

Outras configurações a serem observadas também incluem key_buffer_size , table_open_cache , sort_buffer_size etc. que todas as chamadas resultam em melhor desempenho

PHP:

Em PHP puro você pode criar MySQL Worker onde cada consulta é executada em threads PHP separados
$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

Aqui está um exemplo completo de trabalho do SQLWorker

2:análise de conteúdo HTML


Se você já conhece o problema, fica mais fácil resolver via event loops, Job Queue ou usando Threads.

Trabalhar em um documento de cada vez pode ser um muito, muito processo lento e doloroso. @ka uma vez hackeado usando o ajax para chamar várias solicitações, algumas mentes criativas simplesmente bifurcavam o processo usando pcntl_fork mas se você estiver usando windows então você não pode tirar proveito de pcntl

Com pThreads suportando sistemas Windows e Unix, você não tem essa limitação. É tão fácil quanto .. Se você precisa analisar 100 documentos? Gerar 100 Tópicos... Simples

Verificação 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);

Saída
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

Classe usada

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

Experiência

Tentando analisar 8,714 arquivos com 105,109 links sem threads e veja quanto tempo levaria.

Arquitetura melhor

Gerar muitos threads, o que não é uma coisa inteligente de se fazer na produção. Uma abordagem melhor seria usar Pooling . Tenha um grupo de definir Trabalhadores então pilha com uma Task

Melhoria de desempenho

Tudo bem, o exemplo acima ainda pode ser melhorado. Em vez de esperar que o sistema verifique todos os arquivos em um único thread, você pode usar vários threads para verificar meu sistema em busca de arquivos e empilhar os dados nos Trabalhadores para processamento

3:Atualização do índice de pesquisa


Isso foi praticamente respondido pela primeira resposta, mas há muitas maneiras de melhorar o desempenho. Você já considerou uma abordagem baseada em eventos?

Apresentação do evento


@rdlowrey Citação 1:

@rdlowrey Citação 2:

Por que você não experimenta com event-driven , non-blocking I/O abordagem do seu problema. PHP tem libevent para turbinar seu aplicativo.

Eu sei que esta pergunta é tudo Multi-Threading mas se você tiver algum tempo, pode ver este Nuclear Reactor escrito em PHP por @igorw

Finalmente

Consideração


Acho que você deveria considerar usar Cache e Job Queue para algumas de suas tarefas. Você pode facilmente ter uma mensagem dizendo
Document uploaded for processing ..... 5% - Done   

Em seguida, faça todo o tempo desperdiçando tarefas em segundo plano. Consulte Reduzindo um trabalho de processamento grande para um estudo de caso semelhante.

Perfil


Ferramenta de perfil? Não existe uma ferramenta de perfil único para um aplicativo da web do Xdebug para Yslow são todos muito úteis. Por exemplo. Xdebug não é útil quando se trata de threads porque não é suportado

Não tenho um favorito