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:
- Como se pode usar multi threading em aplicativos PHP
- pcntl executa o mesmo código várias vezes, é necessária assistência
- Melhorar a eficiência do raspador de HTML com pcntl_fork()
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