Alex Elliott
The internet home of a prospective software engineer
This is my personal blog where I discuss projects that I'm currently working on, work I've recently completed, or write about any topic which has caught my interest in the world of Computing from my studies or from my personal research.
Concurrency in PHP
November 13th, 2008
One of the problems you come across when writing real-time applications in PHP is that it is in most cases a linear language, performing the tasks set before it one at a time and doesn’t contain much in the way of tools to help set up concurrent tracks of evaluation.
As far as I’m aware PHP doesn’t contain anything at all for controlling threads, however it does include some process control functions which allows us to use a multi-process model for concurrent programming.
Introducing Process Control
The functions we need come via the Process Control module in PHP. This is not included by default in the PHP Apache module (because it’s more complicated in such cases), if you want to use it for a website you will need to use PHP as a CGI module or compile mod_php with –enable-pcntl, in this case I’ll be testing using the PHP CLI binary, in which it’s included by default.
The key function that this module provides for us is pcntl_fork(). This works much like the fork you may have come across in other languages, it creates a clone of the current process which then computes a separate code path to the parent that called it. The important thing of course being that the clone (or child) process does its computation while the parent carries on with whatever it was doing. This is key to parallelising our PHP applications, and allows us to create responsive applications which can still do lengthy tasks.
Process Control in Use
So where might this be useful? A trivial example would be when you want to perform a task that takes a number of seconds, and you want the user to receive output from the program while it’s being computed. A simple example of this could be the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?php // this is a place-holder for a hypothetical function // which takes a long time to compute, let's say the // eventual answer would be 5... function foo() { sleep(10); return 5; } file_put_contents('tmp',0); // we'll also assume we know the answer isn't 0. // Here's the fork, the process ID will be stored in $pid for the main // program, and it'll be 0 for the child process. $pid = pcntl_fork(); if($pid == -1) die('Fork failed'); // Our fork failed, thus our program did. elseif($pid == 0) { // here's our forked process file_put_contents('tmp',foo()); echo "Done\n"; exit; } // In the meantime we'll keep our parent process looping. $timestamp = time(); while(file_get_contents('tmp') == 0) { if($timestamp != time()) // once a second... echo 'Calculating...',"\n"; // give some output $timestamp = time(); } echo file_get_contents('tmp')."\n"; // output our answer from the fork. ?> |
As you see we have simply made a test-case here, there’s a function with a sleep(10); which takes the place of any long-running function, and while it is running we inform the user that the task is underway, once a second until it is complete. It’s quite a trivial example, but it shows that both the echo statements and the sleep were functioning in parallel when viewing the output, which is predictably as follows:
bash-3.1$ php -f test.php Calculating... Calculating... Calculating... Calculating... Calculating... Calculating... Calculating... Calculating... Calculating... Done 5
Another example might be if you were performing a repetitive task on many targets, such as all the files in a directory. You could loop across the directory forking off a new process which would handle each file, then back in the main loop you simply wait for all of the processes to finish and then wrap up any loose ends you might have.
Conclusion
So there you go, process control. A useful tool if you need to speed up a parallelisable program/algorithm. Of course, in most cases speed isn’t too necessary in PHP applications, so the practical applications of process control aren’t very numerous. In cases where speed is not important, it is usually better to keep the application simple, since it means it is more likely to be correct.
However, if you are writing something real-time, but don’t want to bog down your main application loop – making your application unresponsive, process control comes into its own and will save the day.
Concurrency in zBot
As I mentioned in the previous post, concurrency is something I’ve been meaning to include in zbot for a while now. zbot is a real-time PHP application, and as an IRC bot, a response time of over a second or two is starting to seem sluggish. Sometimes however some responses can’t be given in this length of time because they rely on an external site, and so the bot must wait for a response before it can reply. In such cases I would like the main loop to be free to continue watching for more easily serviced queries. So that it could reply to those first while it is waiting.
It also allows me to safely parcel off largish tasks without having to worry that the bot will ping out, as the core will continue looking for PING packets. For example, I would like to implement a news plugin which would download five or more RSS feeds and then parse them to check for new news stories. This would be ideal for process control, as I could fork off another process which would handle the downloads and parsing while the main bot continues to function.
For this purpose I have written a taskScheduler class to which I can send jobs which are then evaluated in a forked process. The class keeps track of all scheduled jobs, and performs a callback when the job is completed. This might prove to be a useful separate class, so I’ll likely both include it in zbot, and separately on my site with some documentation when it’s finished.
Leave a Reply
Search
Recent Articles
- Expression Editor Update (2)
- Expression Editor Update
- A New Project
- My Little FAQ For PHP Pitfalls
- Musings on Syntax Highlighting for Websites
My Projects
- Expression EditorGraphical Regular Expression Editing Tool
- My Pastebin – PasteSite.ComMy Easy Usable NoPaste/Pastebin Application
Blogroll
- Binary VisionThe Technology Musings of Ed Cradock
- Tim Davies sans vowelsThe Blog of Tim Davies
- WizedAdam McPeake’s Blog
Other Sites
- HideMyAss – Free Web ProxyHide My Ass! Free Proxy and Privacy Tools – Surf The Web Anonymously
- Iam-andy – Design PortfolioThe Design Portfolio of Andy Mallaby
- Zymic – Free Webhosting and MoreFree Web Hosting, Free Templates, Free Tutorials and more! Zymic Webmaster Resources
Archives
- January 2010 (1)
- December 2009 (2)
- November 2009 (1)
- February 2009 (1)
- January 2009 (1)
- December 2008 (1)
- November 2008 (5)
Categories
- arbutus (1)
- c++ (3)
- general (4)
- musing (1)
- php (5)
- polymer (4)
- zbot (3)
- projects (10)
- expressioneditor (3)
- qt (3)
- regular expressions (2)
- web (5)