PHP中的多线程/多任务处理

时间:2012-05-23 06:29:43

标签: php optimization multiprocessing

在PHP中,我们通常在不考虑服务器能力的情况下进行编码。现在有一天甚至PC都有多个内核并处理64位数据。据我所知,PHP引擎本身已经过优化,可以利用多个内核。我们如何能够进一步优化代码以利用多个内核。

换句话说,我想知道将教我编写代码的技术,这些代码更有可能被php引擎平行处理。

我不是要求任何用户定义/开源排队方法,而是以这样的方式编写相同的代码,以便它利用多核并更快地工作。

如果您已经做过类似的事情,请提出您的想法并分享您的经验。

我希望我们可以进一步优化代码。

4 个答案:

答案 0 :(得分:14)

从2000年5月22日PHP4的第一个版本开始,PHP已经有很长时间的线程模型了。

在前端进行线程处理

在Web应用程序的前端创建用户线程没有任何意义;它很难扩展。 Apache Worker MPM二进制文件和mod_php使用的每个客户端模型的线程并不是您想要用来为您的网站提供服务的东西,当然如果您正在使用它,您不希望创建其他线程来直接响应任何Web请求。

为什么前端的线程是个坏主意?

你可能经常听到开发人员说前端的线程没有意义,没有提供这种断言的理由。当您学会以所需方式思考系统时,问题就变得很明显了:

如果客户端脚本在直接响应Web请求时创建8个线程,并且100个客户端同时请求该脚本,则表示您的硬件同时执行 800 线程。

CPU必须看起来和工作方式非常不同才能使其成为一个好主意

我们能做些什么呢?

企业解决方案可能有一个面向公众的PHP网站,但系统的实际大脑是用语言编写的,这些语言对构建企业级解决方案(如Java,C#,C ++或其他任何语言)所需的东西有很好的支持。这一天是。

你应该以同样的方式使用pthreads;通过设计其组件彼此分离的系统,仅通过精心设计的高性能(RPC)API连接,使得设计多线程架构所固有的复杂性完全与面向公众的网站隔离,而且简单,这样一个网站需要的可扩展设置。

你现在可以使用危险码

让我们从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();
?>

无聊,但我希望你能读懂它;)

所以在一个真实的系统中,你并不是真的想要如此明确地创建线程,你肯定只想将任务提交给某些执行器服务,所有复杂的系统,就其多任务需求而言,我见过使用过这样的东西......

<?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();
?>

我已经给你非常简短的解释复杂的事情,你应该尽力阅读:

可在此处找到许多示例:https://github.com/krakjoe/pthreads/tree/master/examples

免责声明:使用线程的服务器架构没有什么问题,但是当你开始创建额外的线程时,你限制了它的可扩展性和按设计执行的能力,我可以想象设计良好的体系结构有能力在前端进行线程,但这并不是一件容易的事情。此外,当涉及高性能Web目标应用程序时,线程并不是工具箱中唯一的东西;研究所有选择。

答案 1 :(得分:9)

使用PHP的最常见方式是通过Apache等多进程Web服务器运行它。这意味着即使PHP本身不具备多核感知能力,操作系统也会尽力平衡可用CPU之间Web服务器进程所产生的负载。

如果你有一个独立的长期运行的PHP程序,你自己在一个进程中运行,你将不得不考虑线程或将程序分解到不同的进程,以便能够利用多个CPU 。哪个更好/更容易取决于您的特定情况:将任务分解为多么容易,需要多少进程间/线程通信,需要多少同步等等。

虽然标准PHP发布本身似乎没有线程支持,但有php-pthreads等扩展允许使用本机pthreads API。

要将长期运行的PHP程序划分为多个进程,您可以使用pcntl库或proc_*函数系列。至于IPC ..这又取决于你的需求。

答案 2 :(得分:1)

因为已经提供了解释所以直接放置代码。所有你问的都可以通过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() ) 
{
}

记住PHP本身并不支持线程。更详细的信息可以在http://blog.motane.lu/2009/01/02/multithreading-in-php/

找到

您也可以按照这个答案解释一下,当它与PHP和代码示例相关时,它会更好一些。

我个人不会使用PHP线程,因为线程主要用于通过将其分成不同的线程来加速进程,如果您的站点获得高流量,那么操作系统本身将管理进程到不同的CPU核心。所以,我认为你不应该担心PHP线程,可能这就是PHP团队没有关注它的原因(这只是我的想法)。

答案 3 :(得分:-1)

PHP并没有真正考虑到多线程(它是围绕短生命周期的请求/响应模型构建的)。虽然有几个选择。

PCNTL扩展:生成和管理子进程。这不是多线程,因为每个子进程都是一个新的PHP实例。因此它非常耗费资源。在Windows中不可用。

PThreads扩展:允许在PHP脚本中生成和管理线程。它是(在我从文档中可以看出来的)在Windows上可用,并且理论上线程至少应该比产生进程更轻量级,但是使用它有很多警告。例如,必须编译PHP以保证线程安全,这会对无线代码的性能产生不利影响,并且可以防止使用不支持线程安全的扩展。

ReactPHP:一个PHP代码库,提供诸如事件循环和非阻塞IO之类的东西。它并没有严格地说支持线程(虽然我知道正在进行提供它们的工作),但它确实提供了许多有用的功能,这些功能应该使线程的需求不那么紧迫。 https://github.com/reactphp/react/wiki/FAQ包括对线程支持状态的讨论。