PHP kvíz (aktualizováno)
Dneska vám přináším malý PHP kvíz. Každou jeho část představuje krátký kus kódu, který s maličkou změnou najednou začne běžet pomaleji, i když dělá stejné množství práce. Vaším úkolem je poznat co to způsobuje a proč. Odpovědi můžete psát do komentářů.
(Update: Přidal jsem jeden nový kvíz a přidal měření na desktopovém CPU, na kterém rozdíly mnohem víc vynikají).
Na začátek něco jednoduchého:
define('FACTOR', 1); $arr = []; for ($i = 0; $i < 100000; $i++) { $arr[$i * FACTOR] = 1; }
Pokud je konstanta FACTOR rovna jedné, smyčka na Atomu proběhne ze 40 milisekund. Pokud se FACTOR rovná 1048576, vykoná se za 84 vteřin.
Co to způsobuje a jak?
Další dvě otázky jsou už o něco zajímavější.
define('INTERVAL', 1000); $arr = []; for ($i = 0; $i < 2000000; $i++) { $arr[$i] = ['a' => 1+1]; } $start = microtime(true); for ($i = 0; $i < 1000000; $i++) { $arr[mt_rand(0, INTERVAL-1)]; } $time = microtime(true) - $start;
Pokud má konstanta INTERVAL hodnotu 1000, poslední smyčka na netbookovém Atomu trvá 3 vteřiny, pokud má hodnotu 2000000, trvá 3.7 vteřin; na desktopovém Haswellu je to pak 0.9 vteřiny pro INTERVAL=1000 a 0.14 vteřiny pro INTERVAL=2000000. Proč je kód až 6x pomalejší, když se indexy generuji z většího intervalu? V jiném jazyku nebo virtuálním stroji by tento rozdíl mohl být ještě větší.
Třetí otázka se nese v podobném duchu.
$arr = []; for ($i = 0; $i < 500000; $i++) { $arr[$i] = ["a" => 1+1]; } $start = microtime(true); for ($i = 0; $i < 500000; $i++) { $idx = mt_rand(0, 500000-1); $idx = $i; // tenhle řádek odstraním $arr[$idx]; } $time = microtime(true) - $start;
Poslední smyčka na netbookovém Atomu proběhne za 1.5 vteřiny, když odstraním
řádek $idx = $i, kód běží o víc jak 20% pomaleji (1.8s). Na
Haswellu se smyčka vykoná za 0.11 vteřin a pokud odstraním onen řádek, tak za
0.4 vteřiny, tedy skoro čtyřikrát pomaleji. Proč, i když dělám stejné množství
práce, ale index se neinkrementuje o jedničku, všechno déle? I tady platí, že
v jiném jazyce nebo jiném prostředí by rozdíl mohl být mnohokrát větší.
Dodatečně přidám ještě jednu kvízovou otázku.
$arr = []; $prefix = ""; // prefix mastavím na "x" for ($i = 0; $i < 2000000; $i++) { $arr[$prefix.$i] = $i; } $start = microtime(true); for ($i = 0; $i < 2000000; $i++) { $arr[$prefix.$i]; } $time = microtime(true) - $start; echo $time, "\n";
Pokud je proměnná prefix prázdný string, poslední smyčka trvá 0.24 vteřiny,
pokud se $prefix rovná stringu "x", trvá 0.36 vteřiny, ale když místo prefixu
použiji postfix (indexace přes $arr[$i.$prefix]), trvá 0.46 vteřiny. Proč se
tak děje?
Odpovědi pište do komentářů, za pár dnů tady zveřejním správné odpovědi.