|
|
 |
January 3rd, 2007, 11:38 PM
|
#1
|
|
Elite Veteran
SuperMember
Join Date: Jul 2003
Location: Southern UK
Age: 35
Posts: 3,133
Thanks: 28
Thanked 22 Times in 19 Posts
|
Multithreaded PHP
Whilst working on a new webmaster tool (which I will unleash to you lot in the future) I ran into an issue...
The tool performs dozens of checks on a web page and then returns a report.
The problem was that the speed was very very slow indeed and I needed a way to speed it up.
What I needed was a way to handle these checks in a multithreaded way (or at least a pseudo multithreaded way) so I rang up the only person I knew who could offer a suggestion (Graham Ellis of Well House Consultants)
He suggested a workaround and whilst it isnt true multithreading, it added severe speed to my application.
Here are the two core files which make it all happen.
This first file is the main php file you hit in your browser and for the sake of this example, needs a url passed in the querystring. The url is then passed to the 6 scripts by way of a command line parameter (yes, you read that right)
Code:
<?php
$url = $_GET['url'];
$scripts = array(
"script1.php",
"script2.php",
"script3.php",
"script4.php",
"script5.php",
"script6.php");
# Set off parallel contacts to each of the scripts
for ($p=0; $p<count($scripts); $p++) {
$fh[$p] = popen("/usr/local/bin/php ".
"/home/yoursite/public_html/" . $scripts[$p] ." " .
$url,"r");
}
########################################
# DO AS MUCH PROCESSING IN HERE AS YOU LIKE
########################################
# your scripts here
# code here is processed whilst the above script calls are being processed
#
#
#
#
# We're done with our work - read back the results from the scripts
for ($p=0; $p<count($scripts); $p++) {
$st = fgets($fh[$p]);
$rs .= $scripts[$p] . " : " . $st ."<br />";
}
print $rs;
?>
What the above does is fire off the 6 scripts in parallel, passing $url to each script as a command line parameter.
It executes each script by executing the php binary itself, so the processes themselves live outside of apache.
The instant the scripts are fired, they work in the background whilst control is passed back to php to continue.
After we've done other intensive processing (whatever code you insert above) we can finally get all the scripts return values.
For this example, here is the code for one of the scripts that is called - note how it reads the url we passed from the command line
Code:
<?
$url = $argv[1];
// code goes here
// in my webmaster tool, each of these scripts does a function
// such as check pageRank, alexa rank, backlinks, etc.
print "this is the returned value";
?>
The above method is best used on very intensive tasks that typically take a long time.
From my own tests, it's best to split up around 50% of the work. With that 50%, farm it out to a few different scripts and execute them with the above method. The other 50% can be processing within the main script before you finally read the results back in.
There are probabally better ways to further optimise and maybe better ways to split up the work load, but all of that experimentation I shall leave up to you.
Obviously this method can only be used in certain situations like mine... it wont make any differnce to scripts that are processor intensive, but for those which are not - this will reall add some speed if your script is suitable for splitting up in this way.
Be sure to post here with any info you gather.
Happy Coding
Digg this article
Last edited by Rob; January 4th, 2007 at 10:01 AM..
|
|
|
January 4th, 2007, 05:04 AM
|
#2
|
|
Reputable Member
Join Date: Jul 2005
Location: Melksham, Wilts, UK
Posts: 293
Thanks: 0
Thanked 0 Times in 0 Posts
|
Re: Multithreaded PHP
Many thanks for the "plug", Rob ... the work you've done and shown me is fascinating - I'll be coming back and running it against a sampling of my pages and it should be a great help to show us how we can improve our placement.
I have used similar techniques (though through Tcl/Expect or Python) in the past to check which systems are available on a network. It was a similar case to yours in that I wanted to check up on some 20 hosts, but couldn't afford to wait for serial ping timeouts. So I "paralleled" them. To this day, I have a Tcl page on our main web sites that, in a single click, tells me about some 10 different servers on which we look after sites ... and I can check from anywhere in the world.
One caution for anyone using this technique. I believe that pipes have a 4k buffer in them, so your popen'd scripts could come to a temporary stop if they generate a lot of output and haven't been "reaped".
|
|
|
January 4th, 2007, 06:39 AM
|
#3
|
|
Elite Veteran
Join Date: May 2006
Location: Las Vegas
Posts: 3,784
Thanks: 0
Thanked 0 Times in 0 Posts
|
Re: Multithreaded PHP
That's cool! I can seriously use that in a project I'm working on!
|
|
|
January 4th, 2007, 06:50 AM
|
#4
|
|
Reputable Member
Join Date: Nov 2003
Location: Australia
Age: 27
Posts: 329
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Altering Power: 0
|
Re: Multithreaded PHP
If it works as you say it does, then I will also be able to use it in a current project. Thanks guys!
|
|
|
January 31st, 2007, 03:00 PM
|
#5
|
|
New Member
Join Date: Jan 2007
Location: argentina
Age: 26
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Altering Power: 0
|
Re: Multithreaded PHP
hi, i also needed some multithreading/parallel task.
i had a different approach, using WebService like interface and sockets.
I have the main file, socket_cli_test. php, the one called by the user in the Browser.
That files calls internally n other ones via socket connection ( HTTP request) and then grabs the answers. Ive also implemented time out, because i needed the whole process to finish before 3 seconds.
here is the code:
socket_cli_test. php
Code:
<?php /* * Created on 31/01/2007 * * Coded by: Ropu * - Buenos Aires, Argentina - z-tests */ error_reporting(E_ALL); $cant_sockets = 9; $timeout = 2.9;
// Write $sockets = array(); $URI = '/~ropu/tests/socket_srv_test.php'; $Host = 'localhost'; $port = 80;
echo "start\n<xmp>";
list($start_m, $start_s) = explode(' ', microtime()); $start = $start_m + $start_s;
// Create a new socket for($i=0; $i<$cant_sockets; $i++) { $sockets[$i] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); }
// Connect to destination address for( $i = 0; $i < $cant_sockets; $i++ ) { socket_connect($sockets[$i], $Host, $port); // socket_set_nonblock($sockets[$i]); socket_set_option($sockets[$i], SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500000)); }
for($i=0; $i<$cant_sockets; $i++) { $ReqBody = $i; $ReqHeader = "POST $URI HTTP/1.1\n". "Host: $Host\n". "User-Agent: Ropu Soft\n". // "Authorization: Basic ".base64_encode($merid.':'.$merkey) . "\n". "Content-Type: application/xml\n". "Connection: close\n". // Important HEADER!!! to avoid delays when doing do{}while(reading)! "Content-Length: ". strlen($ReqBody) ."\n\n". // without this one, post wont work "$ReqBody\n"; socket_write($sockets[$i], $ReqHeader); }
$mid = $start; while($mid-$start < $timeout){ $new_socks = $sockets; // Calculate the remaing time before timeOut $working = $timeout - ($mid-$start); $rsec = (int)($working); $rusec = (int)(($working - $rsec) * 1000000); // Watch for activity in any socket $num_changed_sockets = socket_select($new_socks, $write = NULL, $except = NULL, $rsec , $rusec); for($i=0; $i<count($new_socks); $i++) { // Read all info in the socket do { echo $read = socket_read($new_socks[$i], 2048); }while(!empty($read)); // echo "sock: ". $i . " => " .socket_strerror(socket_last_error($new_socks[$i])) ."\n"; } // Discard used sockets $sockets = array_diff($sockets, $new_socks); // If all sockets are read, don't wait for the timeOut. if(count($sockets) < 1) break; // Calculate actual time list($mid_m, $mid_s) = explode(' ', microtime()); $mid = $mid_m + $mid_s; }
list($end_m, $end_s) = explode(' ', microtime()); $end = $end_m + $end_s; echo "\n\nTardó: ". ($end-$start) ." segs";
?>
socket_srv_test. php
Code:
<?php /* * Created on 31/01/2007 * * Coded by: Ropu * - Buenos Aires, Argentina - z-tests */
// set_time_limit(1); //print_r($_POST); //print_r($HTTP_RAW_POST_DATA); echo "\n"; $_POST['id'] = $HTTP_RAW_POST_DATA; $id = rand(100, 100000); $message_log = fopen('test.log', "a"); fwrite($message_log, sprintf("\n\rIn: %s:- Id: %d %d\n",date("D M j G:i:s T Y"), $id, $_POST['id'] )); echo "In: ".date("D M j G:i:s T Y") . " Id: $id " . $_POST['id'] ."\n"; $delay = rand(1,5); // if($_POST['id'] == 0) // $delay = $_POST['id'] + 2; //$delay = 2; sleep($delay);
fwrite($message_log, sprintf("\n\rOut: %s:- Id: %d %d Delay: %d\n",date("D M j G:i:s T Y"), $id, $_POST['id'], $delay)); echo "\nOut: ".date("D M j G:i:s T Y") ." Id: $id " . $_POST['id'] ." Delay: $delay\n\n"; echo "--------------------------------------------------\n\n"; //print_r($_SERVER); ?>
Feel free to send some feedback and suggestions.
hope it helps,
ropu
|
|
|
January 31st, 2007, 06:38 PM
|
#6
|
|
Elite Veteran
Join Date: May 2006
Location: Las Vegas
Posts: 3,784
Thanks: 0
Thanked 0 Times in 0 Posts
|
Re: Multithreaded PHP
Thanks for sharing!
|
|
|
May 4th, 2007, 08:08 PM
|
#7
|
|
New Member
Join Date: May 2007
Location: Asia
Age: 25
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Altering Power: 0
|
Re: Multithreaded PHP
Hello
can anyone help me??
I am doing the code that Rob giving but there no output it only print out the name of the file.
Is this code supported in window xp because i want to do php multithread.
What i know that php multithread and forking is not supported in window platform and if supported it can only be used in CLI am i right.
plzz someone help me i am stuck to do my project 
|
|
|
May 4th, 2007, 08:42 PM
|
#8
|
|
Reputable Member
Join Date: May 2006
Location: Warrington, UK
Posts: 440
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Altering Power: 0
|
Re: Multithreaded PHP
Grahame... i think its true to say we all love you ... :wub: :wub:
|
|
|
December 20th, 2008, 10:29 PM
|
#9
|
|
New Member
Join Date: Dec 2008
Location: Argentina
Age: 25
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Altering Power: 0
|
Re: Multithreaded PHP
Hey guys, hi, you know, I think you must take a look at this:
http://php.net/manual/en/ref.pcntl.php
What is this?. Well, you are talking about threads, I don't know if you know what is the difference between threads and a processes, but an option to make things go "concurrent" or "parallel" ( it depends if you are working on a multiprocessor system, or in a monoprocessor system, anyway you could make things running faster and more efficiently ) is to use multiprocessing way. You cannot create (not yet) threads in PHP, but you can create child processes (or cuncurrent or parallel processes). If your server is running on Linux family OS, this is very importan, "This PHP extension is not available on Windows platforms", you can use the PCNTL PHP extension, this is a "Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination.".
For example:
Code:
<?php
$pid = pcntl_fork(); // child process creation if ($pid == -1) { // pcntl_fork() returns -1 if something went wrong die('could not fork'); } else if ($pid) { // else, for the child process $pid is zero, but for the // parent process is the Process ID or PID of the // new child process. // here we are the parent section pcntl_wait($status); // waiting for the child process to finish (this is a very good // practice, if you don't do this, you could make the system // crash, because if you just let processes like Orphans or // Zombies no more PIDs will be available for new // processes, so you have to wait for each process to // finish before exit from the script). } else { // we are the child echo "I'm the child process ;-). Wait for me, don't let me be an Orphan or a Zombie!!!"; }
?>
This sample, is the solution to your parallelism problem, you can easy picture this like the following:
<? php
// some code, runing on then main process
// you make "fork" or "pcntl_fork" in this case
// so, you have two processes (the main process -father-, and the new process -son-) running parallel or concurrent to each other, they "fight" to use the processor/s.
// never forget to wait for all the child processes you have created!!
// and exit
?>
The new process, the child one, is an exact copy of the main process, with its own memory slice, it is like to do Ctrl + C and Ctrl + V with the processes on main memory, the only difference between them is, the pcntl_fork returns zero for new child process, and an integer value to the parent process, that is the process id of the new process on your system. That's the way you use to know if you are running on child process or parent process.
If you read more about this, you will be able to do some interesting stuff, like "client-server" application, using sockets, or faster link checker (one process for each url to check, running parallel to each other), and much much more interesting stuff.
Just study this: http://www.php.net/manual/en/intro.pcntl.php
Bye,
Happy coding for everyone! =)
Javier.
|
|
|
 |
LinkBacks (?)
LinkBack to this Thread: http://webforumz.com/php/12595-multithreaded-php.htm
|
| Posted By |
For |
Type |
Date |
| Multithreaded PHP |
This thread |
Refback |
April 26th, 2009 02:55 AM |
| Neowin Forums > [PHP] Download Multiple Files at once |
This thread |
Refback |
April 18th, 2009 12:51 PM |
| [PHP] Download Multiple Files at once - Neowin Forums |
This thread |
Refback |
February 6th, 2009 03:43 AM |
| Multithreaded socket server |
This thread |
Refback |
February 1st, 2009 08:21 PM |
| PFZ | Forum | Hoe maak je een tweede (of achtergrond) proces aan? | |
This thread |
Refback |
January 26th, 2009 10:57 AM |
| Recent php Bookmarks on Delicious |
This thread |
Refback |
September 19th, 2008 03:37 AM |
| DevNetwork Forums • View topic - How to run second php script under the main script |
This thread |
Refback |
September 10th, 2008 02:18 AM |
| Asynchronous function call? : PHP server side scripting (comp.lang.php) |
This thread |
Refback |
August 31st, 2008 07:26 AM |
| [PHP] exit() bzw. die() Effekt, aber nur für die aktuelle Seite - S² Media Support Forum |
This thread |
Refback |
July 27th, 2008 06:22 AM |
| Asynchronous function call? - comp.lang.php | Grupos do Google |
This thread |
Refback |
June 20th, 2008 11:59 AM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
May 8th, 2008 05:22 PM |
| User:Csanz - ChrisDevbox |
This thread |
Refback |
April 25th, 2008 07:27 PM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
April 5th, 2008 09:30 AM |
| Re: Asynchronous function call? |
This thread |
Refback |
April 3rd, 2008 10:58 AM |
| Google Checkout module for Zen Cart (beta) - Page 66 - Zen Cart Support |
This thread |
Refback |
March 16th, 2008 03:38 PM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
March 6th, 2008 07:19 AM |
| Asynchronous function call? - Object Mix |
This thread |
Refback |
February 29th, 2008 08:04 AM |
| Re: Asynchronous function call? |
This thread |
Refback |
December 12th, 2007 08:21 AM |
| Asynchronous function call? |
This thread |
Refback |
November 20th, 2007 05:29 PM |
| php e processi |
This thread |
Refback |
September 3rd, 2007 03:58 AM |
| kiiza's bookmarks tagged with |
This thread |
Refback |
April 25th, 2007 06:22 PM |
| I’m Mike » programming |
This thread |
Refback |
April 10th, 2007 03:05 PM |
| I’m Mike » Blog Archive » Fork PHP! (and speed up your scripts) |
This thread |
Pingback |
April 8th, 2007 10:12 PM |
| digg / ropu / news / dugg |
This thread |
Refback |
April 8th, 2007 09:06 PM |
| Digg - Who dugg or blogged: How to make a multi-threaded PHP page |
This thread |
Refback |
April 4th, 2007 11:00 AM |
| Standards.za.net » PHP |
This thread |
Refback |
April 3rd, 2007 06:21 AM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
March 26th, 2007 05:38 PM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
March 6th, 2007 04:06 AM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
February 24th, 2007 07:38 AM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
February 24th, 2007 05:20 AM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
February 23rd, 2007 10:07 AM |
| Computer!Totaal :: Bekijk onderwerp - php thread |
This thread |
Refback |
February 23rd, 2007 08:56 AM |
| del.icio.us/url/2f62acff1b3bebe25284f85a03dbbc0a |
This thread |
Refback |
February 14th, 2007 03:04 PM |
| charlvn's bookmarks tagged with |
This thread |
Refback |
February 13th, 2007 12:10 PM |
| Google Checkout module for Zen Cart (beta) - Page 66 - Zen Cart Support |
This thread |
Refback |
February 13th, 2007 11:07 AM |
| Digg - Multithreaded PHP with sockets thought HTTP |
This thread |
Refback |
February 1st, 2007 05:37 PM |
| ropu's bookmarks on del.icio.us |
This thread |
Refback |
February 1st, 2007 03:53 PM |
| Planet PHP |
This thread |
Refback |
January 9th, 2007 09:18 PM |
| digg / Bara / news / dugg |
This thread |
Refback |
January 5th, 2007 04:14 AM |
| digg / mindspace / news / dugg |
This thread |
Refback |
January 4th, 2007 11:54 AM |
| digg / JacobHaug / news / dugg |
This thread |
Refback |
January 4th, 2007 11:54 AM |
| digg / crewdesign / news / dugg |
This thread |
Refback |
January 4th, 2007 11:53 AM |
| digg / spinal007 / news / dugg |
This thread |
Refback |
January 4th, 2007 11:53 AM |
| digg / captainflack / news / dugg |
This thread |
Refback |
January 4th, 2007 11:53 AM |
| digg / charlvn / news / dugg |
This thread |
Refback |
January 4th, 2007 11:53 AM |
| digg / ForeverTangent / news / dugg |
This thread |
Refback |
January 4th, 2007 11:52 AM |
| digg / jpmitchell / news / dugg |
This thread |
Refback |
January 4th, 2007 11:52 AM |
| digg / t2dman / news / dugg |
This thread |
Refback |
January 4th, 2007 11:51 AM |
| digg / vitalityjtw / news / dugg |
This thread |
Refback |
January 4th, 2007 11:51 AM |
| digg / rob30 / news / dugg |
This thread |
Refback |
January 4th, 2007 11:51 AM |
| digg / Bryan / news / dugg |
This thread |
Refback |
January 4th, 2007 11:50 AM |
| digg / t2dman / news / dugg |
This thread |
Refback |
January 4th, 2007 11:49 AM |
| digg / vitalityjtw / news / dugg |
This thread |
Refback |
January 4th, 2007 11:48 AM |
| digg / rob30 / news / dugg |
This thread |
Refback |
January 4th, 2007 11:48 AM |
| digg / ForeverTangent / news / dugg |
This thread |
Refback |
January 4th, 2007 11:48 AM |
| digg / charlvn / news / dugg |
This thread |
Refback |
January 4th, 2007 11:48 AM |
| digg / captainflack / news / dugg |
This thread |
Refback |
January 4th, 2007 11:47 AM |
| digg / spinal007 / news / dugg |
This thread |
Refback |
January 4th, 2007 11:47 AM |
| digg / crewdesign / news / dugg |
This thread |
Refback |
January 4th, 2007 11:47 AM |
| digg / JacobHaug / news / dugg |
This thread |
Refback |
January 4th, 2007 11:46 AM |
| digg / mindspace / news / dugg |
This thread |
Refback |
January 4th, 2007 11:46 AM |
| Clug Park |
This thread |
Refback |
January 4th, 2007 08:15 AM |
| Standards.za.net » » Multithreading in PHP |
This thread |
Pingback |
January 4th, 2007 07:52 AM |
| digg - How to make a multi-threaded PHP page |
This thread |
Refback |
January 4th, 2007 12:10 AM |
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|