⬆️ ⬇️

Parallel computing, class wrapper for pcntl_fork ()

I want to show my base class that I use for PHP scripts.

Its advantage is that you can easily "parallelize" the work.

It uses pcntl_fork () with all the consequences.



(tested on linux only)



The essence of the idea:





class some_script extends CliScript

{

protected function processWorker ( $item )

{

$this -> log ( "I'm doing heavy job" );

sleep ( rand ( 1 , 5 ));

$this -> log ( "I'm done doing heavy job" );

}



}



$script = new some_script();

$script -> setWorkers ( 5 );

$script -> run ();



')

in the end, we get one parent process and 5 children doing the “heavy job”.



There are some nuances and limitations: open connections to the database and files can reduce money.



We need a different approach: the parent process should deal with the base and the child processes do the “dirty work” and return the result. For example:



class master_and_workers extends CliScript

{

protected $contracts = array ( 2 , 4 , 5 , 1 , 3 , 7 , 3 , 1 , 4 , 9 , 2 , 4 , 1 );

protected $results ;



protected function processMaster ()

{

foreach ( $this -> contracts as $contract )

{

while ( ! $this -> canStartWorker () ) { sleep ( 1 ); };



$this -> startWorker ( $contract );

}



$this -> waitForChildren ();



var_export ( $this -> results );

}



protected function processWorker ( $item )

{

$this -> log ( "I'm busy for { $item } seconds..." );

sleep ( $item );

$this -> log ( "Job is done." );



return "Job is done. Sleep time was { $item } " ;

}



protected function processResult ( $result )

{

$this -> results [] = $result ;

}



}



$script = new master_and_workers();

$script -> setWorkers ( 3 );

$script -> run ();





A quick explanation if anyone gets confused:



after starting in the parent process, the processMaster () method is executed, which starts the child processes.

The child process runs the processWorker () method.

What the child process returns is stored in a temporary file, after completion, the processResult () method is called in the parent and the result is transferred there.



There are several useful methods in the CliScript class:



getRunningTime () returns the execution time from the start in seconds

countWorkers () returns the number of child processes (it makes sense only in Rodtel process)

log () if the CliScript :: $ file_log file is specified, then it is logged, if not - to the screen. Displays information about "who reports"



To kill the whole company "gently" send a signal SIGTERM to the parent process, there is a primitive handler.



In conclusion.





I can not say that the code is run-in and polished, rather the opposite, but it really helps me to quickly load the CPU with work when necessary.



CliScript class source



If someone has similar developments and is ready to share - I will be very happy.

Source: https://habr.com/ru/post/128396/



All Articles