PHP で CPU 負荷を100%にする

2022-01-23
PHP

PC の潤沢なリソースが遊んでいるので、PHP で負荷をかけていくというコンセプトです。

真面目な話をすると、自作している HTTP サーバーが資源を有効活用できていないので、ともかく PHP で資源を使い切るにはどうしたら良いのか?という肌感を掴むための行動です。

普通のPHP

下記は、とてもシンプルな無限ループです。

1
2
<?php
while(true){}

しかし、これではコアを使いきれません。参考までに top した画像を貼り付けます。

シングルプロセス

ガラガラです。負荷の上がっているコアは1つだけ。これでは Go に敵いません!

マルチプロセス

みんなおなじみの、pcntl_fork を使ってマルチプロセスにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
foreach(range(0,11) as $i){
$pid = pcntl_fork();
if($pid === 0){
while(true){}
}else{
$pids[] = $pid;
}
}

foreach($pids as $pid){
pcntl_waitpid($pid, $status);
}

このコードを実行すると、一気に12コアを使い切れます!やったぜ!

マルチプロセス

ここで夢は叶いましたが、一応マルチスレッドもやっておきます。

マルチスレッド

2022/01/23 現在の状況では、Parallel 拡張も Pthreads 拡張も、普通には PHP8.1 にインストール出来ません。今回はとりあえずやっつけなので、 Parallel に飛んできてた Pull Request のリポジトリのコードからビルドして使うようにしました。

@sji_ch さんの話によると、Parallel に期待する界隈の声はあるものの、現状でメンテが一番されていそうなのは、 https://github.com/pmmp/pthreads とのこと。PHP のマルチスレッド界隈は覗き込むたびにちょっとずつ状況が変化しており、面白いですね。

コードサンプル
※ 12コアのCPUなので、12個コピペしました。お使いのPCのコア数に合わせて変更しましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

$runtime1 = new \parallel\Runtime();
$runtime1->run(function() {
while(true){}
});

$runtime2 = new \parallel\Runtime();
$runtime2->run(function() {
while(true){}
});

//中略

$runtime12 = new \parallel\Runtime();
$runtime12->run(function() {
while(true){}
});

while(true){}

このコードも、見事にコアを使い果たせます。

マルチスレッド

一応、エビデンス(なにゆえ?)のスレッド一覧

マルチスレッド

というわけで、OS が効率良い資源消費をするためには、PHP側のソースコードは、マルチプロセス・またはマルチスレッドを使ってプログラミングすることが必要だということがよくわかりました。

余談

このように、 Loop を使って CPU を使い切るようなコードは busy waiting busy looping spinning 等と呼ばれるようです。今回初めて知りました。日々勉強。

https://en.wikipedia.org/wiki/Busy_waiting