iteratorは遅い?

前に、宴会だけのPHP勉強会で話した(す時間がほとんど無かった)SPLのiteratorについて、思ったより興味もってもらえたので、もちょっと調べてみた。
#というわけで、はてなダイアリーつかってみた。

$arr = array('val-00000',
                 :
             'val-49999');
$arrObj = new ArrayObject($arr);
$iterator = $arrObj->getIterator();
// 配列版
foreach($arr as $key => $val) {
        $tmp = sprintf("'%s',\n", $val);
}

// パターン A.
while ($iterator->valid()) {
    $tmp = sprintf("'%s',\n", $iterator->current());
    $iterator->next();
}

// パターン B.
$offset = 0;
while ($iterator->offsetExists($offset)) {
    $tmp = sprintf("'%s',\n", $iterator->offsetGet($offset++));
}

配列はともかく、パターンAより、オフセットをずらしているだけのパターンBの方が速いだろうとは思っていたけど、予想以上に大差が。

配列版
Offset 10000: [0.0699 sec.] -- [nivcsw 17] -- [VmSize: 29940 kB]
Offset 20000: [0.1403 sec.] -- [nivcsw 27] -- [VmSize: 29940 kB]
Offset 30000: [0.2104 sec.] -- [nivcsw 37] -- [VmSize: 29940 kB]
Offset 40000: [0.2792 sec.] -- [nivcsw 49] -- [VmSize: 29940 kB]
Offset 50000: [0.3491 sec.] -- [nivcsw 60] -- [VmSize: 29940 kB]

パターンA
Offset 10000: [  3.9680 sec.] -- [nivcsw  118] -- [VmSize: 28404 kB]
Offset 20000: [ 26.5991 sec.] -- [nivcsw  574] -- [VmSize: 28404 kB]
Offset 30000: [ 64.3590 sec.] -- [nivcsw 1307] -- [VmSize: 28404 kB]
Offset 40000: [117.0404 sec.] -- [nivcsw 2334] -- [VmSize: 28404 kB]
Offset 50000: [184.6406 sec.] -- [nivcsw 3634] -- [VmSize: 28404 kB]
               ~~~~~~~~~~~~~
パターンB
Offset 10000: [0.0884 sec.] -- [nivcsw 16] -- [VmSize: 28400 kB]
Offset 20000: [0.1764 sec.] -- [nivcsw 28] -- [VmSize: 28400 kB]
Offset 30000: [0.2633 sec.] -- [nivcsw 40] -- [VmSize: 28400 kB]
Offset 40000: [0.3506 sec.] -- [nivcsw 51] -- [VmSize: 28400 kB]
Offset 50000: [0.4390 sec.] -- [nivcsw 62] -- [VmSize: 28400 kB]

もともとSPLのiteraotrは、なんでもforeachで回しちゃえみたいなもの?なので、実際にforeachで回すときにどうなっているのか見ようと、役に立たないクラスを被せてみた。

$obj = new testIterator($arr);
foreach($obj as $val) {
    $tmp = sprintf("'%s',\n", $val);
}

class testIterator extends ArrayObject
{
    public function __constructor(array $arr)
    {
        parent::__constructor($arr);
    }
}

はい、何もかも、ArrayObjectお任せなので、classに意味はありませんが。
で、結果は下記の通り。

Offset 10000: [  4.1064 sec.] -- [nivcsw   97] -- [VmSize: 28400 kB]
Offset 20000: [ 26.6693 sec.] -- [nivcsw  526] -- [VmSize: 28400 kB]
Offset 30000: [ 64.3097 sec.] -- [nivcsw 1238] -- [VmSize: 28400 kB]
Offset 40000: [116.5720 sec.] -- [nivcsw 2202] -- [VmSize: 28400 kB]
Offset 50000: [183.6532 sec.] -- [nivcsw 3467] -- [VmSize: 28400 kB]

うーん、next()とcurrent()を使っているのかな。とりあえず、ぼーっとiteratorを使ってしまうのは怖そう。

こんなところで時間がつきたので、ArrayObjectの中身は別途。

不要とは思いつつ、勉強会LLでのPPT。。。を上げようと思ったら、ファイルアップロードがなかった。
勉強会資料と資料の追記を載せようと はてなダイアリーを書いてみたのに(汗
[後記]別場所におきました。勉強会LLでのPPT