PHP applications, undoubtedly work effectively with multithreading capabilities. Multithreading is something similar to multitasking, but it enables to process multiple jobs at one time, rather than on multiple processes. Since jobs are smaller, and more basic instructions than processes, multithreading may occur within processes.
There are several real-life examples of multithreading from banking to ticket booking. Let us discuss an example of online bus ticket booking, where many users attempting to book available bus tickets at the same time, with multi-threading approach, the application handles different threads ( i.e different users’ request to the server) and process them simultaneously. So that no user is kept waiting for responses from the site when the tickets are unavailable /sold out. By this way, you can handle more customers using the same server capacity.
When multithreading with PHP was not so popular in the world of coding, there was no true solution for paralleling long jobs. We were dependent on forking through pcntl_fork, which includes its own issues and it was difficult to handle the results adequately.
Therefore, using multithreading in PHP comes as a favorable concept in the PHP community. There are different ways to get this parallel processing done and most of which are considered 'Hacky'.
The following section explores what are the commonly used methods to achieve Multithreading in PHP.
1) Setting up Job/Task Queues with Web Server Software
This method enables you to employ multi-processor servers so that you can distribute the processor-intensive task effectively.
- A message, which includes all data required to complete the process is packed and encoded into a JSON String
- This information is sent to queuing the mechanism like AWS SQS, RabbitMQ, Memcache, Redis, BeanstalkMQ, etc.
- A daemon process reads these queued messages at a fixed rate and triggers an HTTP POST to forward the message to a script with all information to execute the task/job
- Then the web server software like Nginx, Apache, and Tomcat handles this process requests in such a way it would do during multiple users hit a website it is hosting
Benefits: It is easy to implement even though it looks like a complicated setup. It can be understandable to a developer who works with generic web stack architecture. In addition, you can include another queue-consuming worker when the queue becomes longer and include more processes - thereby it is highly scalable.
The primary disadvantage is that this architecture is not affordable for all systems or server setups. If your processing needs are on-demand, then your system might face idle server time, which costs more money.
This method is effective when you require frequent batch processing.
2) Process Forking with pcntl_fork
This method allows us to create a parent process or 'forking' - child processes, which are just clones of the parent process meant to perform the task.
In practical cases, the method is tricky to handle because it is hard to maintain a track of the child processes and their runtime needs. Moreover, if they crash or do not exit cleanly, they can block memory space. Overall, this method works well, but it requires some good scripting to ensure proper management & can become bothersome rapidly if errors are not handled.
3) Asynchronous Processing
If we have a group of independent tasks to perform, we can adopt this method as it allows us to process them simultaneously, without affecting/blocking each other. The flow includes:
- A parent process loops around a set of jobs
- For each job, new 'thread' is created to perform the task, and there is no need for the parent process to wait
- The parent process receives notification when the thread has completed & it reassesses the concurrency limit if any.
This method is easy to implement and experts claim that a module called "pThreads" in PHP 7 makes this method more accessible. pThreads is defined as an object-oriented API that delivers entire tools required for multithreading in PHP. Now, PHP apps possess the ability to generate, read, write, execute as well as syncs with Threads, Workers and Threaded objects.
When it comes to implementing asynchronous processing with PHP, compiling PHP with ZTS (Zend Thread Safety) enabled is the first and foremost action we need to do.
Proof of Concept
Let us have a look at how to implement multithreading in PHP with the pThreads extension.
The code below ensures parallelism, but there is no way to control how many processes we can run simultaneously. It will be good to include some concurrent settings to bring some worthwhile performance enhancements. The following screenshot illustrates the upgraded code segments with concurrent property using the pThreads extension. pThreads offers a rich interface, which allows us to create and control multiple threads. Hence, when you have a bunch of things to do simultaneously, think twice before discarding PHP as an option. Threading won’t always be the solution when it is used for specific cases that can be split into separate units of jobs, but it is, nonetheless, a solid tool to have in your toolbox.
The pthreads extension adds interesting benefits. It’s already compatible with PHP7 and a new version just came out. Moreover, the pThreads extension’s repository is available on Github, and it is widespread with examples, explanations, and documentation about its inner mechanism. Upgrade your PHP applications for a multithreaded system to unlock its added capability and find your PHP scripts perform faster.