PHP 多进程的困惑

最近在研究 php 多进程。看到普遍的观点是,多进程对于单核 cpu 没有什么作用。因为 cpu 同时只能运行一个线程,当然同时只能运行一个进程,那么进程调度的开销让你的多进程没有意义。 可是实际运行却发现,多进程比单进程耗时要小的多。请看代码:

<?php
class WebServer
{
    private $list;
    public function __construct()
    {
        $this->list = [];
    }

    public function worker($request){
        $pid = pcntl_fork();

        if($pid == -1){
            return false;
        }

        if($pid > 0){
            return $pid;
        }

        if($pid == 0){

            $time = $request[0];

            $method = $request[1];

            $start = microtime(true);
    
            echo getmypid()."\t start ".$method."\tat".$start.PHP_EOL;

            //sleep($time);

            $c = file_get_contents($method);

            echo getmypid() ."\n";

            $end = microtime(true);

            $cost = $end-$start;

            echo getmypid()."\t stop \t".$method."\tat:".$end."\tcost:".$cost.PHP_EOL;

            exit(0);

        }

    }

    public function master($requests){
        $start = microtime(true);

        echo "All request handle start at ".$start.PHP_EOL;

        foreach ($requests as $request){
            $pid = $this->worker($request);

            if(!$pid){
                echo 'handle fail!'.PHP_EOL;
                return;
            }
            array_push($this->list,$pid);
        }

        while(count($this->list)>0){
            foreach ($this->list as $k=>$pid){
                $res = pcntl_waitpid($pid,$status,WNOHANG);

                if($res == -1 || $res > 0){
                    unset($this->list[$k]);
                }
            }
            usleep(100);
        }

        $end = microtime(true);

        $cost = $end - $start;
        echo "All request handle stop at ".$end."\t cost:".$cost.PHP_EOL;
    }
}

$requests = [
[1,'http://www.sina.com'],
[2,'http://www.sina.com'],
[3,'http://www.sina.com'],
[4,'http://www.sina.com'],
[5,'http://www.sina.com'],
[6,'http://www.sina.com']
];

echo "多进程测试:".PHP_EOL;
$server = new WebServer();
$server->master($requests);

echo PHP_EOL."单进程测试:".PHP_EOL;
$start = microtime(true);
for($i=0;$i<6;$i++){
$c = file_get_contents("http://www.sina.com");
}
$end = microtime(true);
$cost = $end - $start;
echo "All request handle stop at ".$end."\t cost:".$cost.PHP_EOL;

测试结果如下:
多进程测试:

All request handle start at 1524498288.8329
17820 start http://www.sina.com at1524498288.8379
17821 start http://www.sina.com at1524498288.8383
17822 start http://www.sina.com at1524498288.8389
17823 start http://www.sina.com at1524498288.8392
17824 start http://www.sina.com at1524498288.8397
17825 start http://www.sina.com at1524498288.8407
17820 stop http://www.sina.com at:1524498289.5795 cost:0.7415988445282
17824 stop http://www.sina.com at:1524498289.5899 cost:0.7502818107605
17822 stop http://www.sina.com at:1524498289.5968 cost:0.75795722007751
17821 stop http://www.sina.com at:1524498289.6514 cost:0.81310606002808
17823 stop http://www.sina.com at:1524498289.6571 cost:0.81785297393799
17825 stop http://www.sina.com at:1524498289.6614 cost:0.820631980896
All request handle stop at 1524498289.6657 cost:0.83276891708374


单进程测试:

All request handle stop at 1524498293.6477 cost:3.9819581508636

可以看到,多进程比单进程耗时要小的多。

我的服务器是阿里云上的 1G 内存,单核 cpu,不过是 64 位的,不知道这个是否有影响。麻烦 V 友解答,谢谢。

运行代码,需要给 php 加上 pcntl 扩展。

小花花
3周前提问
1 个回答
  • 董俊俊
    董俊俊 3周前 回答了: PHP 多进程的困惑

    你提问里说对了一半。
    时间有两个指标,一个叫墙上钟时间,也就是现实中流逝的时间,另一个叫 CPU 时间,是 CPU 花费在执行程序的时间片的总和。
    使用多线程和多进程,会减少 Wall clock 时间,但会增加 CPU clock 时间。
    对于 CPU 密集型任务来说,单进程单线程效率更高。
    对于经常需要 CPU 等待的任务来说,多进程多线程可以增加 CPU 利用率,减少现实流逝时间。

    更好的选择是事件回调模型,既可以并发多任务,又不需要多线程支持,结合了两者的优点,效率最高。

撰写答案
  • 相似问题