前から気になっていたのでやってみた。
array_map
より foreach
の方が速いという話を聞いたことがあるので、まあ foreach
の方が速いんだろうとは思うものの、どの程度速いのか知りたかった。
というのもLaravelの collect()
ヘルパーが強力過ぎて、もう普通のArrayは使いたくないとまで思ってしまったからだ。
検証方法
次のテストコードを使って計測する。
LaravelのBooting時間とか諸々ツッコミどころはあります。
tests/SpeedTest.php
<?php
use Tests\TestCase;
class SpeedTest extends TestCase
{
public function testCollection()
{
collect(range(1, 1500000))->map(function ($value) {
return $value * 2;
})->filter(function ($value) {
return $value > 10000;
});
}
public function testForeach()
{
$double_me = [];
foreach (range(1, 1500000) as $value) {
$double_me[] = $value * 2;
}
$filter_me = [];
foreach ($double_me as $key => $value) {
if ($value > 10000) {
$filter_me[$key] = $value;
}
}
}
}
やっていることは、
1から1500000までの範囲に対し、2倍して10000より大きい要素を取得
である。間違っていたらすみませんm(_ _)m
結果
Collectionの方
vagrant@homestead:~/Code/Laravel$ php vendor/bin/phpunit tests/SpeedTest.php --filter=Collection
PHPUnit 4.8.35 by Sebastian Bergmann and contributors.
.
Time: 1.28 seconds, Memory: 262.02MB
foreachの方
vagrant@homestead:~/Code/Laravel$ php vendor/bin/phpunit tests/SpeedTest.php --filter=Foreach
PHPUnit 4.8.35 by Sebastian Bergmann and contributors.
.
Time: 1.06 seconds, Memory: 178.00MB
やはり若干foreachの方が速い。
しかもforeachは変数を2つ使っているにも拘わらず、メモリ消費量がかなり少なかった。
内部でどう処理されているかは知らない。
所感
まあこんな大量の範囲を扱うコードは現実にはほぼ使わないだろうから、ほとんど気にすることは無いのでは。
それよりも可読性の方が大切と考える。
foreachは一旦変数に入れるから、変数のスコープをcollect()より気にしてしまう。