Saltar al contenido

Ejecutando funciones en paralelo

Solución:

Si desea ejecutar tareas paralelas en PHP, consideraría usar Gearman. Otro enfoque sería usar pcntl_fork (), pero preferiría trabajadores reales cuando se basa en tareas.

El único tiempo de espera que sufre es entre obtener los datos y procesarlos. De todos modos, el procesamiento de los datos está bloqueando por completo (simplemente tiene que esperar). Es probable que no obtenga ningún beneficio más allá de aumentar la cantidad de procesos a la cantidad de núcleos que tiene. Básicamente, creo que esto significa que la cantidad de procesos es pequeña, por lo que programar la ejecución de 2 a 8 procesos no suena tan horrible. Si le preocupa no poder procesar datos mientras recupera datos, en teoría podría obtener sus datos de la base de datos en bloques pequeños y luego distribuir la carga de procesamiento entre unos pocos procesos, uno para cada núcleo.

Creo que me alineo más con el enfoque de procesos secundarios de bifurcación para ejecutar realmente los subprocesos de procesamiento. Hay una demostración brillante en los comentarios de la página del documento pcntl_fork que muestra una implementación de una clase de demonio de trabajo

http://php.net/manual/en/function.pcntl-fork.php

<?php 
declare(ticks=1); 
//A very basic job daemon that you can extend to your needs. 
class JobDaemon{ 

    public $maxProcesses = 25; 
    protected $jobsStarted = 0; 
    protected $currentJobs = array(); 
    protected $signalQueue=array();   
    protected $parentPID; 

    public function __construct(){ 
        echo "constructed n"; 
        $this->parentPID = getmypid(); 
        pcntl_signal(SIGCHLD, array($this, "childSignalHandler")); 
    } 

    /** 
    * Run the Daemon 
    */ 
    public function run(){ 
        echo "Running n"; 
        for($i=0; $i<10000; $i++){ 
            $jobID = rand(0,10000000000000); 

            while(count($this->currentJobs) >= $this->maxProcesses){ 
               echo "Maximum children allowed, waiting...n"; 
               sleep(1); 
            } 

            $launched = $this->launchJob($jobID); 
        } 

        //Wait for child processes to finish before exiting here 
        while(count($this->currentJobs)){ 
            echo "Waiting for current jobs to finish... n"; 
            sleep(1); 
        } 
    } 

    /** 
    * Launch a job from the job queue 
    */ 
    protected function launchJob($jobID){ 
        $pid = pcntl_fork(); 
        if($pid == -1){ 
            //Problem launching the job 
            error_log('Could not launch new job, exiting'); 
            return false; 
        } 
        else if ($pid){ 
            // Parent process 
            // Sometimes you can receive a signal to the childSignalHandler function before this code executes if 
            // the child script executes quickly enough! 
            // 
            $this->currentJobs[$pid] = $jobID; 

            // In the event that a signal for this pid was caught before we get here, it will be in our signalQueue array 
            // So let's go ahead and process it now as if we'd just received the signal 
            if(isset($this->signalQueue[$pid])){ 
                echo "found $pid in the signal queue, processing it now n"; 
                $this->childSignalHandler(SIGCHLD, $pid, $this->signalQueue[$pid]); 
                unset($this->signalQueue[$pid]); 
            } 
        } 
        else{ 
            //Forked child, do your deeds.... 
            $exitStatus = 0; //Error code if you need to or whatever 
            echo "Doing something fun in pid ".getmypid()."n"; 
            exit($exitStatus); 
        } 
        return true; 
    } 

    public function childSignalHandler($signo, $pid=null, $status=null){ 

        //If no pid is provided, that means we're getting the signal from the system.  Let's figure out 
        //which child process ended 
        if(!$pid){ 
            $pid = pcntl_waitpid(-1, $status, WNOHANG); 
        } 

        //Make sure we get all of the exited children 
        while($pid > 0){ 
            if($pid && isset($this->currentJobs[$pid])){ 
                $exitCode = pcntl_wexitstatus($status); 
                if($exitCode != 0){ 
                    echo "$pid exited with status ".$exitCode."n"; 
                } 
                unset($this->currentJobs[$pid]); 
            } 
            else if($pid){ 
                //Oh no, our job has finished before this parent process could even note that it had been launched! 
                //Let's make note of it and handle it when the parent process is ready for it 
                echo "..... Adding $pid to the signal queue ..... n"; 
                $this->signalQueue[$pid] = $status; 
            } 
            $pid = pcntl_waitpid(-1, $status, WNOHANG); 
        } 
        return true; 
    } 
}

puedes usar “PTHREADS”

muy fácil de instalar y funciona muy bien en Windows

descargar desde aquí -> http://windows.php.net/downloads/pecl/releases/pthreads/2.0.4/

Extraiga el archivo zip y luego

  • Mueva el archivo ‘php_pthreads.dll’ al directorio php ext .

  • Mueva el archivo ‘pthreadVC2.dll’ al directorio php .

luego agregue esta línea en su archivo ‘php.ini’:

extension=php_pthreads.dll

guarda el archivo.

acabas de terminar 🙂

ahora veamos un ejemplo de cómo usarlo:

class ChildThread extends Thread {
    public $data;

    public function run() {
        /* Do some expensive work */

        $this->data="result of expensive work";
    }
}

$thread = new ChildThread();

if ($thread->start()) {     
    /*
     * Do some expensive work, while already doing other
     * work in the child thread.
     */

    // wait until thread is finished
    $thread->join();

    // we can now even access $thread->data
}

para obtener más información sobre PTHREADS, lea los documentos de php aquí:

PTHREADS DE PHP DOCS

  • si está usando WAMP como yo, entonces debe agregar ‘pthreadVC2.dll’ en wamp bin apache ApacheX.XX bin y también editar el archivo ‘php.ini’ (misma ruta) y agregar la misma línea como antes

    extensión = php_pthreads.dll

¡BUENA SUERTE!

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *