Oct 16, 2009

php からのディスクアクセス

php だという時点で既にアレなんだが…

php からディレクトリにある全ファイルの一覧を取得する処理のパフォーマンスを exec()popen()opendir() を利用した処理で比較してみる。

方法は単純にテスト用のディレクトリに 500 ファイルを用意して、 それぞれの関数を使用してファイル名一覧を取得する処理を 10 回実行した場合の処理速度を計測する。

exec("ls -1") 0.774762
popen("ls -1") 0.865914
opendir() 0.136642

外部 shell を実行しないので opendir() が早いだろうとは予想していたが、 これほど差が出るとは思わなかった。
パフォーマンスを優先する場合は勿論だが、 余計なプロセスを生成しないので opendir() が地球に優しい様だ。

  1<?
  2
  3    $func = array("byexec", "bypopen", "byopendir");
  4
  5    for($i=0; $i<3; $i++){
  6        $dist = array();
  7        $start[$i] = gett();
  8        for($j=0; $j<100; $j++)
  9            $dist[$j] = $func[$i]("/tmp/test");
 10        $end[$i] = gett();
 11
 12        printf("%-10s:%f\n", $func[$i], $end[$i] - $start[$i]);
 13    }
 14
 15    function    byexec($dir)
 16    {
 17
 18        exec("ls -1 $dir", $output);
 19
 20        return($output);
 21
 22    }
 23
 24    function    bypopen($dir)
 25    {
 26
 27        if(($fp = popen("ls -1 $dir", "r"))){
 28            while($buf = fgets($fp))
 29                $output[] = trim($buf);
 30            pclose($fp);
 31
 32        }
 33
 34        return($output);
 35
 36    }
 37
 38    function    byopendir($dir)
 39    {
 40
 41        if($dir = dir($dir)){
 42            while($file = $dir->read())
 43                $outout[] = trim($file);
 44            $dir->close();
 45        }
 46
 47    }
 48
 49    function    gett()
 50    {
 51
 52        $t = gettimeofday();
 53        return((float)($t['sec'] + $t['usec'] / 1000000.0));
 54
 55    }
 56
 57?>
    

ついでにシェルの glob なパターン指定を利用して 指定した文字列にマッチするファイル名の一覧取得を行う場合のテストもしてみた。

20090219000 から 20090219499 までの500個のファイルの中から、 200902192?? にマッチするファイル名の一覧取得で時間を計測してみる。

exec("ls -1 200902192??") 0.883770
popen("ls -1 200902192??") 0.902392
opendir()→preg_match("/200902192../") 0.188792
glob("/200902192../") 0.203928

exec()popen() が遅いのは相変わらずだが、 preg_match()の呼出しが意外に早かったのが驚き。
正規表現のマッチ処理って基本的に相当時間がかかる筈なんだが…
glob() はファイルシステムに自分でアクセスしてる様なので早い。
複雑なパターン指定が必要ならpreg_match()の方が柔軟だが、 シェルに渡せる程度のパターン指定なら glob() を利用するのが 可読性やメンテナンス性と性能が両立できて良いのかも?

Edit this entry...

wikieditish message: Ready to edit this entry.
















A quick preview will be rendered here when you click "Preview" button.