sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo hace un buen uso de las CPU multinúcleo en sus aplicaciones PHP/MySQL?

Introducción

PHP tiene Multi-Threading apoyo que puede aprovechar al máximo de muchas maneras. He podido demostrar esta habilidad Multi-Threading en diferentes ejemplos:

Una Búsqueda rápida daría recursos adicionales.

Categorías

1:Consultas MySQL

MySQL es totalmente multiproceso y hará uso de múltiples CPU, siempre que el sistema operativo las admita. También maximizaría los recursos del sistema si se configura correctamente para el rendimiento.

Una configuración típica en my.ini que afectan el rendimiento del hilo es:

thread_cache_size = 8

thread_cache_size se puede aumentar para mejorar el rendimiento si tiene muchas conexiones nuevas. Normalmente, esto no proporciona una mejora notable en el rendimiento si tiene una buena implementación de subprocesos. Sin embargo, si su servidor ve cientos de conexiones por segundo, normalmente debe configurar thread_cache_size lo suficientemente alto para que la mayoría de las conexiones nuevas usen hilos almacenados en caché

Si utiliza Solaris entonces puedes usar

thread_concurrency = 8 

thread_concurrency permite que las aplicaciones le den al sistema de subprocesos una pista sobre la cantidad deseada de subprocesos que deben ejecutarse al mismo tiempo.

Esta variable está obsoleta a partir de MySQL 5.6.1 y se elimina en MySQL 5.7. Debe eliminar esto de los archivos de configuración de MySQL cada vez que lo vea, a menos que sean para Solaris 8 o anterior.

InnoDB: :

No tiene tales limitaciones si está utilizando Innodb tiene el motor de almacenamiento porque es totalmente compatible con la concurrencia de subprocesos

innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks

También puede consultar innodb_read_io_threads y innodb_write_io_threads donde el valor predeterminado es 4 y se puede aumentar hasta 64 dependiendo del hardware

Otros:

Otras configuraciones para mirar también incluyen key_buffer_size , table_open_cache , sort_buffer_size etc., lo que resulta en un mejor rendimiento

PHP:

En PHP puro, puede crear MySQL Worker donde cada consulta se ejecuta en subprocesos 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

Aquí hay un ejemplo de trabajo completo de SQLWorker

2:análisis de contenido HTML

Si ya conoce el problema, lo hace más fácil de resolver a través de bucles de eventos, cola de trabajos o el uso de subprocesos.

Trabajar en un documento uno a la vez puede ser muy, muy Proceso lento y doloroso. @ka una vez que se abrió camino usando ajax para llamar a solicitudes múltiples, algunas mentes creativas simplemente bifurcaron el proceso usando pcntl_fork pero si está usando windows entonces no puedes aprovechar pcntl

Con pThreads compatible con sistemas Windows y Unix, no tiene esa limitación. Es tan fácil como... ¿Si necesita analizar 100 documentos? Engendrar 100 subprocesos... Sencillo

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

Salida

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

Clase utilizada

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

Experimentar

Intentando analizar 8,714 archivos que tienen 105,109 enlaces sin hilos y ver cuánto tiempo tomaría.

Mejor Arquitectura

Generar demasiados subprocesos, lo que no es algo inteligente en producción. Un mejor enfoque sería usar Pooling . Tener un grupo de definir Trabajadores entonces pila con una Task

Mejora del rendimiento

Bien, el ejemplo anterior aún se puede mejorar. En lugar de esperar a que el sistema escanee todos los archivos en un solo subproceso, puede usar varios subprocesos para escanear mi sistema en busca de archivos y luego apilar los datos en Workers para su procesamiento

3:Actualización del índice de búsqueda

Esto ha sido respondido en gran medida por la primera respuesta, pero hay muchas formas de mejorar el rendimiento. ¿Ha considerado alguna vez un enfoque basado en eventos?

Evento de presentación

@rdlowrey Cita 1:

@rdlowrey Cita 2:

¿Por qué no experimentas con event-driven? , non-blocking I/O acercamiento a su problema. PHP tiene libevent para potenciar su aplicación.

Sé que esta pregunta es todo Multi-Threading pero si tienes algo de tiempo puedes mirar este Reactor nuclear escrito en PHP por @igorw

Finalmente

Consideración

Creo que deberías considerar usar Cache y Job Queue para algunas de sus tareas. Puede tener fácilmente un mensaje que diga

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

Luego haz todo el tiempo perdiendo tareas en segundo plano. Consulte Reducir un gran trabajo de procesamiento para un estudio de caso similar.

Perfiles

Herramienta de perfilado? No existe una herramienta de perfil única para una aplicación web de Xdebug a Yslow son todos muy útiles. P.ej. Xdebug no es útil cuando se trata de subprocesos porque no es compatible

No tengo un favorito