dlaczego nie warto uzywac foreach ?

testcase wyglada tak:
jest sobie tablica:

  • 10224 elementow
  • 10 znaków każdy element
  • 356954 znakow to dlugosc powstalego po zlaczeniu stringa

funkcja mierzaca czas:


function t(){
list($usec, $sec) = explode(" ",microtime());
return ((float)$usec + (float)$sec);
}

test1 (while):

$t1 = t();
$r = '';
while ( list($k, $v) = each($test) )
{
$r .= sprintf('key: %s | value: %s
‘, $k, $v);
}
$t2 = t();

test2 (foreach):

$r = '';
foreach ($test as $k => $v)
{
$r .= sprintf('key: %s | value: %s
‘, $k, $v);
}
$t3 = t();

rezultat

rezultat jest generowany przy kazdym wejsciu na strone.

juz wszyscy wiedza, czemu nie powinno sie uzywac foreach() ? ;)

update:
testy byly wykonywane na sofcie:

php jako cgi, poprzez suphp

a tutaj linki do zrodel wykorzystanego przeze mnie testu:
foreach:while1.php (807 bajtow)
foreach:while_array.php (141 kilobajtow)

i nie smiac sie z pieknej tablicy :P do celow testowych byla super ;)

update2:
no to dalem dupy. na calej linii. gdyby nie piecu, to bym nawet o tym nie wiedzial… ;) chujnia, chyba bede musial przestac uzywac mojej ulubionej konstrukcji :P a mialo byc tak milo… :P

tylko czemu mi az tak glupio ? ;)


Liczba komentarzy: 7

  1. 1 Był poniedziałek, 06 czerwiec 2005 roku gdy o godzinie 17:02 przyszedł piecu i stwierdził:

    while (t2 - t1): 5.48362731934E-05
    foreach (t3 - t2): 0.0457820892334

    Może się mylę, ale to pierwsze wygląda na szybsze ;)

  2. 2 Był poniedziałek, 06 czerwiec 2005 roku gdy o godzinie 22:33 przyszedł MySZ i stwierdził:

    mylisz sie ;)

    pierwsze to wynik t2 - t1: wyszlo, ze ta akcja trwala ponad 5s, jakies 5,5s. i tyle trwa dzialanie petli w while()
    natomiast za pomoca foreach (zapomnialem dodac ze testy byly na paache1 i php5.0.4), zajelo to 0.046s. “lekka” roznica :)

    jako dodatek, o czym tez nie wspomnialem wczesniej, zanim zaczelem jechac whilem i testowac, puscilem, dla rozgrzania sie procesora, dokladnie ta sama petle while(). dopiero pozniej pierwsze pobranie czasu, petla while(), drugie pobranie czasu, petla foreach(), trzecie pobranie czasu i wyniki. foreach jest szybszy ponad 100x (!) (z dokladnoscia do 3miejsc po przecinku: 5.484 / 0.046 = 119,217 !!!)

  3. 3 Był wtorek, 07 czerwiec 2005 roku gdy o godzinie 16:24 przyszedł piecu i stwierdził:

    No zaraz, ale w tym pierwszym mamy taki e-05 na końcu, co oznacza, że robi nam się z tego 0.0000548362731934 sekundy…

  4. 4 Była środa, 08 czerwiec 2005 roku gdy o godzinie 00:50 przyszedł MySZ i stwierdził:

    wiesz co… ponizyles mnie… tzn samo to zrobilem, ale Ty to mi uswiadomiles ;)
    jak to sie stalo, ze nie zauwazylem tej koncoweczki, to ja nie wiem. kurde, ale glupio ;)
    no nic, poprawilem tresc wpisa i tyle. wyjde jak sie przestane wstydzic :P

  5. 5 Był czwartek, 13 lipiec 2006 roku gdy o godzinie 21:59 przyszedł kg i stwierdził:

    Szybkość wyżej przedstawionych konstrukcji zależy od wielkości tablicy… a w powyższym teście brakuje resetowania wskaźnika tablicy
    $t1 = t();

    $r = '';
    reset($test);
    while ( list($k, $v) = each($test) )
    {
    $r .= sprintf('key: %s | value: %s', $k, $v);
    }

    $t2 = t(); ;)

  6. 6 Był poniedziałek, 17 lipiec 2006 roku gdy o godzinie 15:21 przyszedł MySZ i stwierdził:

    Hm, nie da się ukryć, że masz rację. Stara wersja: tests/foreach:while1.php
    Nowa wersja: tests/foreach:while2.php

    Różnica całkiem znaczna, czyli (przynajmniej w wersji PHP5) foreach() jest jednak sensowną alternatywą dla while(). Zarówno ze względu na czytelność, jak i szybkość. Dzięki za zwrócenie uwagi :)

  7. 7 Był czwartek, 20 lipiec 2006 roku gdy o godzinie 02:51 przyszedł urzenia.net i stwierdził:

    php: foreach vs while, odsłona druga…

    Kilka dni temu, Mariusz Jakubowski aka kg zauważył jeden, dość poważny brak w moich testach dotyczących szybkości foreach() i while(), mianowicie brak w odpowiednim miejscu reset()-owania tablicy. Dość diametralnie zmieniło to …

A Ty? Co o tym myślisz?

Możesz używać w komentarzach następujących znaczników:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Sblam! Antyspam