16

在 PHP 中,我们通常在不考虑服务器功能的情况下进行编码。现在,即使是 PC 也有多个内核并处理 64 位数据。据我所知,PHP 引擎本身经过优化以利用多核。我们程序员如何才能进一步优化代码以利用多核。

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

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

如果您已经在做这样的事情,请提出您的想法并分享您的经验。

我希望应该有办法进一步优化代码。

4

4 回答 4

21

自 2000 年 5 月 22 日 PHP4 的第一个版本发布以来,PHP 拥有线程模型已经很长时间了。

前端线程

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

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

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

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

CPU 的外观和工作方式必须非常不同,才能成为一个好主意

我们对于它可以做些什么呢 ?

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

您应该以相同的方式使用 pthread;通过设计其组件彼此分离的系统,仅通过精心设计的高性能 (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 目标应用程序,线程并不是工具箱中唯一的东西。研究你所有的选择。

于 2014-06-06T07:07:33.737 回答
10

使用 PHP 的最常见方式是通过多进程 Web 服务器(例如 Apache)运行它。这意味着即使 PHP 本身不支持多核,操作系统也会尽最大努力平衡可用 CPU 之间由 Web 服务器进程创建的负载。

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

虽然标准 PHP 发行版本身似乎没有线程支持,但有一些扩展,例如php-pthreads,允许使用本机pthreadsAPI。

要将长时间运行的 PHP 程序划分为多个进程,您可以使用pcntl库或proc_*函数族。至于IPC ..再次,这取决于您的需求。

于 2012-05-23T06:41:32.560 回答
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 团队不关注它的原因(这只是我的想法)。

于 2014-06-05T15:39:54.283 回答
-2

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

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

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

ReactPHP:一个 PHP 代码库,提供诸如事件循环和非阻塞 IO 之类的东西。严格来说,它不支持线程(尽管我知道提供它们的工作正在进行中),但它确实提供了许多有用的功能,应该可以减少对线程的需求。https://github.com/reactphp/react/wiki/FAQ包括对线程支持状态的讨论。

于 2014-06-05T15:52:04.940 回答