PHP CLI 模式多子程式任務處理

楊圓建發表於2018-09-28
<?php

$total = 1000;
$num   = 100;

$per = $total / $num;

$isMaster = true;

$child = [];
$c = 1;

$t1 = microtime(true);
echo '模擬佇列資料非同步處理開始' . PHP_EOL;
while (true) {
    $t2 = microtime(true);
    echo "第 {$c} 次主迴圈開始" . PHP_EOL;
    $fork_error = false;
    for ($i = 1; $i <= $num; $i++) {
        $pid = pcntl_fork();

        if ($pid === -1) {
            $fork_error = true;
            break;
        }
        if ($pid > 0) {
            $child[] = $pid;
        } else {
            if ($pid === 0) {
                $t4 = microtime(true);
                echo "非同步執行緒 {$i} 寫入開始" . PHP_EOL;
                $child_time = time();
                $pdo        = new Pdo('mysql:host=mysql-5.7.20-v1;dbname=test', 'root', '123456', [
                    PDO::ATTR_PERSISTENT => true,
                ]);
                for ($j = 0; $j < $total; $j++) {
                    $time = microtime(true);
                    $sth  = $pdo->prepare('insert into rand(`rand`, `time`) values (:rand, :time)');
                    $sth->bindValue(':rand', $j, PDO::PARAM_INT);
                    $sth->bindValue(':time', $time, PDO::PARAM_INT);
                    $sth->execute();
                }
                $pdo = null;
                $id  = getmypid();
                $t5 = microtime(true);
                echo "非同步執行緒 {$i} 寫入結束,總耗時: " . ceil(($t5 - $t4) * 1000) . ' ms' . PHP_EOL;
                exit(0);
            }
        }
    }
    if ($fork_error) {
        continue;
    }
    while(count($child)) {
        foreach($child as $k => $pid) {
            $res = pcntl_waitpid($pid, $status, WNOHANG);
            if(-1 == $res || $res > 0) {
                unset($child[$k]);
            }
        }
    }

    $t3 = microtime(true);
    echo "第 {$c} 次主迴圈結束,耗時:" . ceil(($t3 - $t2) * 1000) . ' ms' . PHP_EOL;
    $c += 1;
    if($c > 10) {
        break;
    }
    sleep(3);
}
echo '模擬佇列資料非同步處理結束' . PHP_EOL;
本作品採用《CC 協議》,轉載必須註明作者和本文連結
smithyj

相關文章