📜 ⬆️ ⬇️

Almost true multithreading with php 5

Once again, I read about multithreading in php rather its complete absence and all sorts of crutches in the form of non-blockable sockets . That's just where I came across an interesting article which described a very simple and effective way of thread parallelization. Based on this material, he wrote a small class to facilitate his work in the future.

So the threads.php class code :
<?php

class Threads {
public $phpPath = 'php' ;

private $lastId = 0 ;
private $descriptorSpec = array (
0 => array ( 'pipe' , 'r' ),
1 => array ( 'pipe' , 'w' )
);
private $handles = array ();
private $streams = array ();
private $results = array ();
private $pipes = array ();
private $timeout = 10 ;

public function newThread ( $filename , $params = array ()) {
if ( ! file_exists ( $filename )) {
throw new ThreadsException( 'FILE_NOT_FOUND' );
}

$params = addcslashes ( serialize ( $params ), '"' );
$command = $this -> phpPath . ' -q ' . $filename . ' --params "' . $params . '"' ;
++ $this -> lastId ;

$this -> handles [ $this -> lastId ] = proc_open ( $command , $this -> descriptorSpec , $pipes );
$this -> streams [ $this -> lastId ] = $pipes [ 1 ];
$this -> pipes [ $this -> lastId ] = $pipes ;

return $this -> lastId ;
}

public function iteration () {
if ( ! count ( $this -> streams )) {
return false ;
}
$read = $this -> streams ;
stream_select ( $read , $write = null , $except = null , $this -> timeout );
/*

$read
*/

$stream = current ( $read );
$id = array_search ( $stream , $this -> streams );
$result = stream_get_contents ( $this -> pipes [ $id ][ 1 ]);
if ( feof ( $stream )) {
fclose ( $this -> pipes [ $id ][ 0 ]);
fclose ( $this -> pipes [ $id ][ 1 ]);
proc_close ( $this -> handles [ $id ]);
unset ( $this -> handles [ $id ]);
unset ( $this -> streams [ $id ]);
unset ( $this -> pipes [ $id ]);
}
return $result ;
}

/*


*/

public static function getParams () {
foreach ( $_SERVER [ 'argv' ] as $key => $argv ) {
if ( $argv == '--params' && isset ( $_SERVER [ 'argv' ][ $key + 1 ])) {
return unserialize ( $_SERVER [ 'argv' ][ $key + 1 ]);
}
}
return false ;
}

}

class ThreadsException extends Exception {
}

?>


Now for an example, create test.php :
<?php
$start = microtime ( true );

require './threads.php' ;

$threads = new Threads;

for ( $i =0 ; $i <10 ; $i ++ ) {
$threads -> newThread ( './delay.php' , array ( 'delay' => rand ( 1 , 5 )));
}

while ( false !== ( $result = $threads -> iteration ())) {
if ( ! empty ( $result )) {
echo $result . " \r\n " ;
}
}

$end = microtime ( true );
echo "Execution time " . round ( $end - $start , 2 ) . " \r\n " ;

?>


And delay.php which it calls:
<?php

require './threads.php' ;

if ( $params = Threads :: getParams ()) {
sleep ( $params [ 'delay' ]);
echo 'Wait for ' . $params [ 'delay' ] . ' s.' ;
}

?>

')
As a result of test.php, we get the following:
Microsoft Windows [Version 6.1.7100]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.

Z:\home\labs\www\threads>php test.php
Wait for 1 s.
Wait for 5 s.
Wait for 4 s.
Wait for 5 s.
Wait for 5 s.
Wait for 5 s.
Wait for 3 s.
Wait for 3 s.
Wait for 2 s.
Wait for 4 s.
Execution time 5.58

Z:\home\labs\www\threads>

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


All Articles