Optimalizace zbytečných polí v PHP
Předpokládejme, že programátor má za úkol
najít součet celých čísel od 1 do 100000000.
Náš programátor napsal elegantní řešení této úlohy, takto:
<?php
echo array_sum(range(1, 100000000));
?>
Krásné řešení, že? Na jeden řádek a tak dále. Ale nefunguje! Zkuste spustit tento kód a vypíše chybu o tom, že jste požadovali příliš mnoho operační paměti.
Hmm, 100000000 není tak moc?
Nebo je? Počítejme. Funkce range
vytváří pole s 100000000 čísly.
Předpokládejme, že PHP alokuje na číslo 2 bajty
- pak pro uložení našeho pole bude potřeba
200000000 bajtů, tedy asi
200 megabajtů operační paměti.
Ve skutečnosti bude potřeba mnohem více
operační paměti kvůli tomu, že PHP má velmi
velké režijní náklady při ukládání pole.
Například u mě text chyby uvádí,
že se snažím alokovat 4294967304
bajtů - to je asi 4 gigabajty!
Je nyní jasné, proč vyhazuje chybu - výrazně jsme překročili povolený limit paměti.
Není tak těžké přepsat náš skript na jiný, téměř nespotřebovávající operační paměť:
<?php
$sum = 0;
for ($i = 1; $i <= 100000000; $i++) {
$sum += $i;
}
echo $sum;
?>
A ještě lépe použijeme matematické řešení:
<?php
$n = 1000000;
$sum = $n * ($n + 1) / 2;
echo $sum;
?>
Programátor měl za úkol najít faktoriál zadaného čísla. Vyřešil to následovně:
<?php
$n = 100;
echo array_product(range(1, $n));
?>
Vysvětlete, co je na tomto kódu špatně. Přepište kód na optimalizovanější.
Programátor měl za úkol najít
počet číslic, pomocí kterých lze
zapsat všechna celá čísla od 1 do 1000000.
Vyřešil to následovně:
<?php
echo strlen(implode('', range(1, 1000000)));
?>
Vysvětlete, co je na tomto kódu špatně. Přepište kód na optimalizovanější.
Programátor měl za úkol najít
počet čísel dělitelných beze zbytku
7, nacházejících se v zadaném
intervalu. Vyřešil to následovně:
<?php
$arr = [];
for ($i = 0; $i <= 1000; $i++) {
if ($i % 7 == 0) {
$arr[] = $i;
}
}
echo count($arr);
?>
Vysvětlete, co je na tomto kódu špatně. Přepište kód na optimalizovanější.
Programátor měl za úkol najít součet dělitelů čísla. Vyřešil to následujícím způsobem:
<?php
$num = 320;
$divs = [];
for ($i = 0; $i <= $num; $i++) {
if ($num % $i == 0) {
$divs[] = $i;
}
}
echo array_sum($divs);
?>
Vysvětlete, co je na tomto kódu špatně. Přepište kód na optimalizovanější.