PHPで実行を一時停止する、sleep関数を含む4つの方法
はじめに
PHPには。プログラムの実行を意図的に一時停止(遅延)させる関数があります。本記事では、その基本書式や実際に使用したソースコードおよびブラウザを基に、その関数の使い方を紹介し、一時停止が必要な場面についても言及します。
PHPにおける一時停止の方法
ここでは、PHPにおける実行の一時停止を行う、合計4つの関数を紹介します。
sleep関数
sleep関数の基本的な書式は以下の通りです。
sleep (一時停止させる秒数);
「sleep(1)」のように引数に int 型の数値を使用して時間を指定することで、指定した秒数だけ実行を一時停止できます。もし負の値を指定して実行した場合はエラー(E_WARNING)が発生します。sleep関数を使用した例を以下に示します。
※下記以降は、冗長性の回避のため、 <?php ?>を抜粋したものを示します。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Sample</title> </head> <body> <?php ini_set('date.timezone', 'Asia/Tokyo'); echo nl2br(" 実行時点の時刻 :".date('h:i:s') ."\n"); sleep(5); echo "5 秒後の時刻:".date('h:i:s'); ?> </body> </html>
上記のプログラムによってプログラムを実行した時刻と、その実行から5秒後の時刻が下記のように表示されます。ちなみに、ソースコード中のnl2br関数は、”\n”タグの場所に自動でHTMLの<br />タグを入れて、ブラウザ上で改行されたものを表示できる関数です。
実行時点の時刻 :03:35:26 5 秒後の時刻:03:35:31
またループ関数内でsleep関数を使用すると、以下に示すように指定した秒数おきに実行を一時停止できます。
<?php for($s=1;$s<11;$s++){ sleep(1); echo nl2br(" 実行開始から $s 秒経過\n"); } ?>
上記を実行すると、以下のように表示されます。
実行開始から 1 秒経過 実行開始から 2 秒経過 (一部、省略します。) 実行開始から 9 秒経過 実行開始から 10 秒経過
usleep
usleep関数の書式は以下のとおりです。
usleep (マイクロ秒);
usleep関数は、マイクロ(100万分の1)秒単位でプログラムの実行を遅延します。この関数は、sleep関数と同様にint 型の数値で一時停止させたい時間を指定して使用します。usleep関数を使用して100ミリ秒ごとに時刻を表示する例を以下に示します。
<?php ini_set('date.timezone', 'Asia/Tokyo'); for($i=1;$i<6;$i++){ $nms = microtime(true); //マイクロ秒までの時間を取得 $mls = (int)(($nms - (int)$nms) * 1000); //小数点以下3桁を取り出す $mlsStr = str_pad($mls, 3, "0", STR_PAD_LEFT); // 桁の整理 echo nl2br(date('h:i:s').".$mlsStr\n"); usleep(100000); } ?>
ソースコード中の「桁の整理」とは、microtime関数で取得した時刻の小数点以下が「.001~」のように、0から始まる場合、$mlsには「1」が格納されます。その結果、現在時刻が「00:00:00.001」ではなく、「00:00:00.1」となってしまいます。これを回避するために、str_pad関数で桁の整理を行います。
上記を実行すると、以下のように表示されます。
03:34:49.422 03:34:49.526 03:34:49.630 03:34:49.734 03:34:49.839
time_nanosleep
time_nanosleep関数の書式は以下の通りです。
time_nanosleep (秒数, ナノ秒);
time_nanosleep関数は、一時停止させたい時間を秒単位とナノ(10億分の1)秒単位で指定することができます。返り値は遅延が成功した時にtrueを、失敗した時にfalseを返します。遅延処理が中断した場合は、「残りの秒数」と「残りのナノ秒数」からなる連想配列を返します。time_nanosleep関数を使用した例を以下に示します。
<?php $s=1; //一時停止させたい秒数 $n=500000; //一時停止させたいナノ秒数 $slpTime = time_nanosleep($s, $n); if ($slpTime === true) { $n/=1000; echo "成功:$s 秒と $n マイクロ秒だけ一時停止しました。\n"; } elseif ($slpTime === false) { echo "失敗:一時停止できませんでした。\n"; } elseif (is_array($slpTime)) { //配列が戻り値の時 $seconds = $slpTime['seconds']; $nanoseconds = $slpTime['nanoseconds']; echo "シグナルによって中断しました。\n"; echo "残りの秒数は $seconds 秒と $nanoseconds ナノ秒です。"; } ?>
上記を実行してtrueが返ってくると、以下のように表示されます。
成功:1 秒と 500 マイクロ秒だけ一時停止しました。
time_sleep_until
time_sleep_until関数の書式は以下のとおりです。
time_sleep_until (秒数);
引数はfloat型で指定でき、指定したタイムスタンプまでプログラムの実行を一時停止できます。ただし、引数に負の値を使用して、過去のタイムスタンプを指定した場合はエラー(E_WARNING)が発生します。time_sleep_untilを使用した例を以下に示します。
<?php echo "Unixタイムスタンプ:",time(); time_sleep_until(time() + 1); //1秒後 echo "<br />"; echo "1秒後のUnixタイムスタンプ:",time(); echo "<br /><br />"; echo "Unixタイムスタンプ(マイクロ秒単位):",microtime(true); time_sleep_until(microtime(true) + 0.5); //0.5秒後 echo "<br />"; echo "1秒後のUnixタイムスタンプ(マイクロ秒単位)",microtime(true); ?>
上記を実行すると、以下のように表示されます。
Unixタイムスタンプ:1600237787 1秒後のUnixタイムスタンプ:1600237788 Unixタイムスタンプ(マイクロ秒単位):1600237788.0048 0.5秒後のUnixタイムスタンプ(マイクロ秒単位)1600237788.5054
sleep関数などによる一時停止が必要な場面
これまでPHPにおけるプログラムの実行を一時停止する方法を紹介してきましたが、これらの関数は次のような場面で使用されます。
- デバッグの際のバグの発見 - プログラムの実行時間を計測し、多くの時間を要している部分を確認してバグの修正をすることができます。
- 無限ループによるコンピュータ負荷の低減 - 無限ループの長時間の実行はCPUへの不可が多く、メモリリークの原因となる可能性があります。そこで意図的にループを一時停止するsleep関数などを使用することで、処理がsleep関数へ移行し、コンピュータの不可を下げることができます。
- 大量のリクエスト時のサーバー負荷の低減 - 大量のリクエストが連続して送り続けられると、サーバーへの負荷は大きくなります。この対策として、sleep関数などが処理の終わりに実行されるようにしておくと、プログラムを遅延することができ、サーバーへの負荷が小さくなります。
まとめ
本記事では、PHPにおいてプログラムの実行を一時停止(遅延)させる関数を合計4つ、使用例を含めて紹介しました。前半で紹介した<!DOCTYPE html></html>までを、PHPファイルにコピー&ペーストして、各コードの<?php ?>の間を置き換えるだけで、すべての関数を試すことができます。そのため、PHPに慣れている方はもちろん、まだPHPに慣れていない方も本記事で紹介したソースコードを試していただけると幸いです。