PHPでは、コマンドを実行するための関数(sytem関数やexec関数)が用意されていますが、このような関数を使ってコマンドをうまく利用すると、プログラムの実行スピードを大幅に上げられる場合があります。

forやforeachによる繰り返し処理は、PHPが比較的苦手とする処理(時間がかかる処理)の一つです。
数が少ないうちはいいですが何万という繰り返しが入ってくると、処理はかなり重くなります。

以下は、ログファイルを分析するプログラム例で、10時台のアクセス数を調べています。
一つ目の方は全部PHPで、二つ目の方はコマンドを利用しています。環境はLinux系OSです。

<?php
//全ての処理をPHPで行う

$start_time getTime();

$file file('access_log');
$counter 0;

foreach (
$file as $data) {
  
//10:xx:xxという文字列があるかどうか
  
if (preg_match('/10:[0-5][0-9]:[0-5][0-9]/'$data)) {
    
$counter++;
  }
}

$end_time getTime();

var_dump($counter);
var_dump($end_time $start_time);

//より正確なタイムスタンプを入手するための関数。
function getTime() {
  
$arr explode(' 'microtime());
  return 
$arr[1] + $arr[0];
}
?>

<?php
//コマンドを利用するプログラム

$start_time getTime();

$cmd 'grep 10:[0-5][0-9]:[0-5][0-9] access_log | wc -l';
exec($cmd$status$result);

$end_time getTime();

var_dump($result);
var_dump($end_time $start_time);


function 
getTime() {
  
$arr explode(' 'microtime());
  return 
$arr[1] + $arr[0];
}

?>

今回の例で使用したコマンドですが、

  • grep (パターン) (ファイル名):正規表現で検索し、マッチした行を出力する。
  • wc (ファイル名やデータ)     :単語数を出力する。「-l」オプションをつけた場合は行数を出力する。

というものです。

また、「|」でコマンドをつなぐと、直前のコマンドの出力結果を次のコマンドの引数に渡します。

プログラムの実行結果ですが、ログファイルが1行だと、

  • コマンド不使用:0.00096607208251953秒
  • コマンド使用  :0.023474931716919秒

となり、繰り返し処理が無ければコマンドを使わない方が速くなりますが、

15000行のログファイルだと、

  • コマンド不使用:0.20867109298706秒
  • コマンド使用  :0.10673499107361秒

と、倍近くの差が出ました。

さらに倍の30000行だと

  • コマンド不使用:0.41866302490234秒
  • コマンド使用  :0.17369604110718秒

となり、繰り返し処理が増えるほど差が大きくなることがわかります。

ちなみに、今回ご紹介したコマンドはLinux系OSのもので、通常Windowsでは使えません。

あくまでPHPのプログラムなので、コマンドを使い過ぎるのはどうかと思いますが、UNIXコマンドには強力なものがたくさんあるので、状況に合わせてうまく使っていきましょう。



(アシアル 牧野克俊)


この記事は、アシアルが運営するPHP開発者のためのポータル&コミュニティサイト「PHPプロ!」で毎週配信しているPHP・TIPSメーリングリストを再録したものです。
同サイトでは、他にもPHP最新ニュースや、困ったときのQ&A掲示板、初心者向けのPHP講座など、PHP開発者をサポートする情報を掲載しています。