4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ループの処理速度をいい加減に検証してみた

Posted at

はじめましての方ははじめまして。
そうでない方も忘れていると思いますのではじめまして。

今回は単純にループの処理速度が知りたくなりました。
でもこの程度のことならば、すでに調べた人が何人もいるようです。
http://ameblo.jp/mingw/entry-10385952873.html
http://blog.generace.co.jp/2013/06/21/894
と思ったのですが、真逆の結論が出てしまいました。
はたして for foreach while で本当に速いのは?

ということで、以下のコードを作ってみました。
なお、 PHP 5.4 で検証しています。

$r = [0,0,0];
$range = 100000;
$c = range(0,$range-1);
for($a = 0;$a < 10;$a++){
  $t = microtime(true);
  for($i = 1;++$i < $range;)$i;
  $r[0] += microtime(true) - $t;
  $t = microtime(true);
  foreach($c as $i)$i;
  $r[1] += microtime(true) - $t;
  $t = microtime(true);
  $i = 0;
  while(++$i < $range)$i;
  $r[2] += microtime(true) - $t;
}
var_dump($r);

あくまでいい加減な検証なので、コーディングスタイルとか読みやすさとか、そういうのは無視しました。
(本当はワンライナーで記述しています)
処理としては、各ループで 0 ~ 99,999 までループする処理を 10 回ループして、それぞれの合計時間を計算しています。
range は処理時間が大きいらしいので、ループの外に記述しました。
結果はどうかというと、

array(3) {
  [0]=>
  float(0.042150497436523)
  [1]=>
  float(0.036016702651978)
  [2]=>
  float(0.023873090744019)
}

一番上から for foreach while です。
for がやや遅くて、 while がやや速いといった結果に。
while が遅いという情報が多いのですが、真逆になりました。
http://d.hatena.ne.jp/tweeeety/20130416/1366096299
ループ回数を増やすと変わるのでしょうか。

ini_set("memory_limit",-1);
$r = [0,0,0];
$range = 1000000;
$c = range(0,$range-1);
for($a = 0;$a < 10;$a++){
  $t = microtime(true);
  for($i = 0;++$i < $range;)$i;
  $r[0] += microtime(true) - $t;
  $t = microtime(true);
  foreach($c as $i)$i;
  $r[1] += microtime(true) - $t;
  $t = microtime(true);
  $i = 0;
  while($i < $range)$i++;
  $r[2] += microtime(true) - $t;
}
var_dump($r);

結果

array(3) {
  [0]=>
  float(0.5011191368103)
  [1]=>
  float(0.44765543937683)
  [2]=>
  float(0.24919891357422)
}

変わった気がしないです。

そういえば、 while が遅いとしているソースは配列処理を念頭に置いた、より実用的なものです。
ということで、配列の中身を参照してみました。

$r = [0,0,0];
$range=100000;
$c = range(0,$range-1);
for($a = 0;$a < 10;$a++){
  $t = microtime(true);
  for($i = 0;++$i < $range;)$c[$i];
  $r[0] += microtime(true) - $t;
  $t = microtime(true);
  foreach($c as $i)$i;
  $r[1] += microtime(true) - $t;
  $t = microtime(true);
  $i = 0;
  while($i < $range)$c[$i++];
  $r[2] += microtime(true) - $t;
}
var_dump($r);

結果

array(3) {
  [0]=>
  float(0.067676544189453)
  [1]=>
  float(0.035441637039185)
  [2]=>
  float(0.065758228302002)
}

while が遅くなり、 foreach が最速になりました。
ところで、前掲のページをよく見ると、 while と一緒に list や each を使っています。
これらを使うとどうなるのでしょうか。

$r=[0,0,0];
$range=100000;
$c=range(0,$range-1);
for($a=0;$a<10;$a++){
  $t=microtime(true);
  for($i=0;++$i<$range;)$c[$i];
  $r[0]+=microtime(true)-$t;
  $t=microtime(true);
  foreach($c as $i)$i;
  $r[1]+=microtime(true)-$t;
  $t=microtime(true);
  $i=0;
  while(list(,$i)=each($c))$c[$i];
  $r[2]+=microtime(true)-$t;
}
var_dump($r);
array(3) {
  [0]=>
  float(0.066687345504761)
  [1]=>
  float(0.0352942943573)
  [2]=>
  float(4.7683715820312E-5)
}

while がとんでもないことに。
ケタ違いどころか、 3 ケタも違う結果になりました。
これがバージョンの差か、マシンの差か、はたまた別の要因かは分かりません。
(いい加減なので、テストが間違っている可能性もあり)
ただ、検索結果を信じるのではなく、自分で実験するのが大事なようです。

ただし、どの結果でも for は最遅のようです。
他の言語だと一般的なループだと思うので、以外な落とし穴かもしれません。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?