Multi Threading / Multi Tasking in PHP

2020-05-23 05:06发布

问题:

In PHP we normally do coding without considering what the server is capable of. Now a days even PCs have multiple cores and process 64 bit data also. As far as I know the PHP engine itself is optimised to take advantage of multiple cores. How can we programmers can optimize further the code to take advantage of multiple cores.

In other words I want to know the techniques that will teach me to write code which will be more likely to be considered by php engine to process parallely.

I'm not asking for any user defined / open source queuing method but to write the same code in such a way that it takes advantage of multi core and works faster.

Please suggest your thoughts and share your experience if you already are doing something like this.

I am hoping there should be way we can optimize code further.

回答1:

PHP has had a threading model for a very long time, since the first release of PHP4, May 22nd 2000.

Threading at the frontend

Creating user threads at the frontend of a web application doesn't make any sense; it is extremely difficult to scale. The thread per client model that the Apache Worker MPM binary and mod_php employ is not really something you want to use to serve your websites, certainly if you are using it, you do not want to create additional threads in direct response to any web requests.

Why are threads at the frontend a bad idea ?

You may often hear developers say threads at the frontend do not make sense, without providing the rationale for such an assertion. When you learn to think about systems in the required way the problem becomes obvious:

If a client script creates 8 threads in direct response to a web request, and 100 clients request the script simultaneously, you are requesting that your hardware execute 800 threads concurrently.

CPU's would have to look and work very very differently indeed to make that a good idea

What can we do about it ?

Enterprising solutions might well have a PHP website facing the public, but the actual brains of the system are written in languages that have good support for those things you require to build enterprising solutions such as Java, C#, C++ or whatever the language-of-the-day is.

You should use pthreads in the same way; by designing systems whose component parts are separated from one another, only connected by well designed, high performance (RPC) API's, such that the complexity inherent in designing a multi-threaded architecture is isolated completely from your public facing websites, and the simple, scalable setup that such a website will require.

U can now haz codes

Let's start at the beginning with Hello World:

<?php
class My extends Thread {
    public function run() {
        printf("Hello World\n");
    }
}

/* create a new Thread */
$my = new My();

/* start the Thread */
$my->start();

/* do not allow PHP to manage the shutdown of your Threads */
/* if a variable goes out of scope in PHP it is destroyed */
/* joining explicitly ensures integrity of the data contained in an objects */
/* members while other contexts may be accessing them */
$my->join();
?>

Boring, but I hope you read it ;)

So in a real system, you don't really want to be creating threads so explicitly, you surely want to just submit tasks to some executor service, all of the complex systems, in the sense of their multi-tasking requirements, I have ever seen use such things ...

<?php
class My extends Threaded {
    public function run() {
        printf("Hello World from %s#%lu\n",
            __CLASS__, Thread::getCurrentThreadId());   
    }
}

/* create a Pool of four threads */
/* threads in a pool are created when required */
$pool = new Pool(4);

/* submit a few tasks to the pool */
$tasks = 100;
while ($tasks--) {
    $pool->submit(new My());
}

/* shutting down the pool is tantamount to joining all workers */
/* remember what I said about joining ? */
$pool->shutdown();
?>

I have given you very brief explanations of complicated things, you should endeavor to read all you can:

  • https://gist.github.com/krakjoe/6437782
  • https://gist.github.com/krakjoe/9384409
  • http://php.net/pthreads

Many examples can be found here: https://github.com/krakjoe/pthreads/tree/master/examples

Disclaimer: There's nothing really wrong with a server architecture that uses threading, but the moment you start to create additional threads, you restrict it's scalability and ability to perform as it was designed, I can imagine well designed architectures that do have the ability to thread at the frontend, but it is not an easy thing to aim for. Additionally, threading is not the only thing in the toolbox when it comes to high performance web targeted applications; research all your options.



回答2:

The most common way of using PHP is running it through a multi-process web server such as Apache. This means that even if PHP itself is not multi-core aware, the operating system will do its best to balance the load created by the web server processes between the available CPUs.

If you have a stand-alone long-running PHP program that you run in a process on its own, you'll have to look into either threading or breaking the program into different processes to be able to take advantage of multiple CPUs. Which is better/easier depends on your particular situation: how easy it is to break your tasks into pieces, how much inter-process/thread communication is needed, how much synchronization you need, etc.

While the standard PHP distribution itself does not seem to have threading support, there are extensions such as php-pthreads that allow the usage of the native pthreads API.

For dividing a long-running PHP program into several processes you can use the pcntl library or the proc_* families of functions. As for IPC.. again, it depends on your needs.



回答3:

Well as the explanation has already been provided so putting the code directly. All you asked can be achieved with Threads.

require_once( 'Thread.php' );

// test to see if threading is available
if( ! Thread::available() ) 
{
   die( 'Threads not supported' );
}

// function to be ran on separate threads
function paralel( $_limit, $_name ) 
{
    for ( $index = 0; $index < $_limit; $index++ ) 
    {
        echo 'Now running thread ' . $_name . PHP_EOL;
        sleep( 1 );
    }
}

// create 2 thread objects
$t1 = new Thread( 'paralel' );
$t2 = new Thread( 'paralel' );

// start them
$t1->start( 10, 't1' );
$t2->start( 10, 't2' );

// keep the program running until the threads finish
while( $t1->isAlive() && $t2->isAlive() ) 
{
}

Remember PHP itself doesn't support Threads. More detailed info can be found here http://blog.motane.lu/2009/01/02/multithreading-in-php/

You can also follow this answer, which explains a bit better when it's about PHP and Threads with a code example as well.

I personally would not go with PHP Threading because threads are mostly used to speed up process by splitting it into different threads and if your site is getting high traffic then OS will itself manage Processes onto different Cores of CPU. So, I don't think you should worry about PHP threading and may be this is the reason that PHP Team is not focusing on it (that's just my thought).



回答4:

PHP isn't really engineered with multi-threading in mind (it's built around a short-lifetime request/response model). There are a couple of options though.

PCNTL extenstion: Spawn and manage child processes. This isn't multithreading, as each child process is a new PHP instance. It's therefore pretty resource intensive. Not available in Windows.

PThreads extension: Allows spawning and management of threads within a PHP script. It is (as far as I can tell from the docs) available on Windows, and threads should in theory at least be a bit more lightweight than spawning processes, but there are an awful lot of caveats for using it. For example, your PHP has to be compiled for thread safety, which can have a detrimental effect on performance of unthreaded code, and can prevent the use of extensions that don't support thread safety.

ReactPHP: A library of PHP code that provides things such as an event loop and non-blocking IO. It doesn't strictly speaking support threads (though I understand there's work underway to provide them), but it does provide a lot of useful functionality that should make the need for threads less pressing. https://github.com/reactphp/react/wiki/FAQ includes a discussion of the state of thread support.