Optimalizace kódu
Školení, která pořádám
Už jsem četl několik článků o optimalizaci PHP kódu, které popisují, že jeden způsob zápisu stejného kódu je rychlejší než druhý. Článek většinou obsahuje skript, který na začátku změří funkcí microtime čas, pak opakovaně provede nějaký kód, na konci opět změří čas a na základě toho určí nejrychlejší metodu. Ti pečlivější kód spustí několikrát, aby se vyhnuli možným výchylkám způsobeným vnějšími okolnostmi, ti se znalostmi vnitřností PHP zrychlení i vysvětlí.
Jestli teď čekáte, že představím několik zaručených optimalizačních triků, tak vás asi zklamu. Proč? Např. WeberBlog objevně popisuje fantastické zrychlení 0.15 s při 2.000.000 průchodech cyklu, což může mít ve vytížených aplikacích prý velký vliv. Můžete si snadno vypočítat, že na webu s milionem shlédnutých stránek měsíčně a dvou cyklech na stránku to je úspora 0.0000058% času – to se vážně moc nevyplatí, pokud je s tím spojená menší přehlednost kódu. Těžiště zrychlení je zkrátka v něčem jiném než v tom, jaký alternativní zápis použít. Rychlý kód dělají správné datové struktury a algoritmy, správná konfigurace, případně pokročilejší techniky jako cachování nebo rozkládání zátěže.
Jaké jsou další zaručené triky? Ilia Alshanetsky popisuje pomalost funkce strlen a doporučuje ji nahradit za !isset($foo[5])
, $i++
je také zbytečně pomalé, každý ví, že print je významně pomalejší než echo a že pro výpis dlouhých textů je lepší vystoupit z PHP kódu. Stejný autor také doporučuje používat include "./file.php"
místo include "file.php"
. Já bych to spíš doporučil kvůli zamezení kolizí se soubory v ostatních adresářích include_path. Jinde se můžete dočíst, že apostrofy jsou rychlejší než uvozovky, include je mnohem rychlejší při používání absolutních cest, switch je rychlejší než několik elseif a str_replace je rychlejší než strtr.
Možná byste se také někde dozvěděli (nebo si to můžete změřit), jestli je rychlejší "ahoj $a"
, "ahoj {$a}"
nebo 'ahoj ' . $a
nebo jaká je nejrychlejší možnost z !$var
, !strlen
, a empty
(byť všechno znamená něco jiného).
Určitě nechci nikoho nabádat k záměrnému používání pomalejších konstrukcí. Čitelnost kódu by ale vždy měla mít přednost. Pokud také máte pocit, že vaše aplikace běží pomalu, nesnažte se např. přepsat všechny uvozovky na apostrofy, žádného zrychlení tím nedosáhnete.
Jak tedy vytvořit rychlejší kód? Pište efektivní algoritmy, navrhněte správně datové struktury, používejte indexy v databázi, na jednoduchou kontrolu řetězce nepoužívejte v dlouhých cyklech regulární výrazy, ale např. funkce pro práci s řetězci nebo třeba funkci is_numeric. Pokud regulární výrazy použijete, vyhněte se Posixovým a použijte Perlové, které jsou podstatně rychlejší a navíc silnější. Pokud existuje vestavěná funkce řešící nějaký problém (např. pro převod kódování znaků), tak ji použijte a nepište vlastní – v podstatě vždy bude ta uživatelská pomalejší. Použít můžete i různé cachování, ať už na úrovni HTTP, PHP kódu (APC, eAccelerator, Zend Optimizer) nebo jeho výstupu.
Neméně důležitá je také správná kompilace PHP, konfigurace a nastavení okolního prostředí. Kvalitní informace jsou k dispozici např. v Přednáškách tvůrců PHP.
Přijďte si o tomto tématu popovídat na školení Výkonnost webových aplikací.
Diskuse
Myslím, že naopak strtr je rychlejší než str_replace, protože prochází pole jen jednou. Každopádně každá funkce pracuje trošku jinak a nelze je automaticky zaměňovat.
Ale jinak souhlasým, že jeden chybějící index dokáže víc zpomalit aplikaci, než milión dvojitých uvozovek prokládaných printy ;)
Myšleno bylo toto:
<?php
str_replace(array("a", "b"), array("c", "d"), "abcd");
strtr("abcd", array("a" => "c", "b" => "d"));
strtr("abcd", "ab", "cd"); // případně
?>
V tomto případě str_replace řetězec prochází také jenom jednou a podle Ilii by měl být rychlejší.
Není to pravda - str_replace bude řetězec procházet dvakrát. Stačí lehká modifikace a můžeš si to ověřit:
<?php
// vrátí dbdd
str_replace(array("a", "c"), array("c", "d"), "abcd");
// vrátí cbdd
$b = strtr("abcd", array("a" => "c", "c" => "d"));
?>
Takže strtr je prakticky vždy rychlejší.
Máš úplnou pravdu, kontroloval jsem to i ve zdrojácích. str_replace() pravděpodobně bude rychlejší pouze v některých speciálních případech (např. krátký prohledávaný řetězec).
http://ilia.ws/archives/73-PHPWorks-Perfor…-Slides.html, slide 32:
<?php
$src_str = file_get_contents("some_big_file");
$src = array('abc', 123, 'text');
$dst = array('cba', 321, 'txet');
$s = microtime(1);
for ($i = 0; $i < 10000; $i++)
str_replace($src, $dst, $src_str);
$e = microtime(1);
echo ($e - $s) . "\n"; // 5.69 seconds
$new_rep = array_combine($src, $dst);
$s = microtime(1);
for ($i = 0; $i < 10000; $i++)
strtr($src_str, $new_rep);
$e = microtime(1);
echo ($e - $s) . "\n"; // 54.42 seconds
?>
Prodávám, jak jsem koupil.
lukas:
a co je lepsi zhlediska vykonu, efektivnosti, prehlednosti, prasarnosti
printf('<li><a href="index.php?var=%s">%s</a></li>', $row['id'], $row['name']);
nebo
<li><a href="index.php?var=
<?php echo $row['id'];
?>">
<?php echo $row['name']; ?></a></li>
jakub:
prvni je podle me cele "spatne" ...
echo je rychlejsi nez printf a je podle me lepsi psat php do html a ne generovat html pomoci php minimalne z duvodu prehlednosti ... protoze kdyz mate html a v nem php editor vam vse krasne zvyrazni :)
martinpav:
Lenze pomocou printf/sprintf si velmi lahko mozete vytvorit jednoduche "sablony" ktore mozete mat pekne pokope. Koli zmene potom vobec nemusite liezt do kodu. Nehladiac na to ze mozte zmenit format zobrazovania bez upravy kodu.
tomáš_M:
Ideální je oddělit HTML od PHP úplně (smarty a další) - nevím co výkon, ale přehlednost je bez debat nejlepší
Anonym:
Som to trochu skusal a:
<?php
echo "<span style='display: none;'>";
$repeat = 1000000;
$speed1 = 0;
$speed2 = 0;
$keys = array();
$s = microtime(1);
for($i = 0; $i < $repeat; $i++):?>a
<?php endfor;
$e = microtime(1);
$speed1 = ($e - $s);
$s = microtime(1);
for($i = 0; $i < $repeat; $i++){
echo "a";
}
$e = microtime(1);
$speed2 = ($e - $s);
echo "</span>
Speed 1: $speed1<br />
Speed 2: $speed2";
?>
Vysledok:
Speed 1: 1.87455105782
Speed 2: 1.68907189369
Taze je zbytocne vychadzat z php codu a pisat to v html, len preto, ze ti to editor zvirazni! Ja pomaly prestavam kodovat html a pisem uz len cisto php, ale nikdy mi nevadilo, ze mi to editor nezvyrazni.
A to nehovorim, ze html sa zvykne vypisovat takto:for($i = 0; $i < $repeat; $i++):
?>
a
<?
endfor; //a to je potom o 2 sekundy dlksie.
A opravte ma ked sa milim, ale server prechadza kod postupne, narazi na php tak si zavola parser, ten poziadavku spracuje a vrati html (mozno som tresol kktinu, ale nekde som to videl napisane). A cim viac poziadaviek, tym pomalsie to ide. Takze ja som zato aby sa php nepremiesavalo s html.
Jakub Vrána :
Přečti si článek ještě jednou. Rychlost není vše, přehlednost kódu je leckdy mnohem důležitější. Kolik stojí MHz výkonu procesoru a kolik stojí vteřina času programátora? (Navíc s přihlédnutím k tomu, že cena prvního jde neustále dolů, kdyžto cena druhého zase nahoru.)
Navíc efektivní kód skutečně nedělají takovéto nanosekundové optimalizace.
BoneFlute:
"A opravte ma ked sa milim, ale server prechadza kod postupne, narazi na php tak si zavola parser, ten poziadavku spracuje a vrati html"
Opravím :-) Server kod neprochází. Pokud má soubor mime php, tak se zavolá parser. Ten postupně vykoná všechny konstrukce
<?php .. ?>. Vše ostatní tam prdne, jak je.
Diskuse je zrušena z důvodu spamu.