Optimalizace na straně klienta v PHP. Tipy pro optimalizaci PHP skriptů. Jak budeme testovat

V tomto článku chci uvést několik tipů, pomocí kterých můžete výrazně urychlit zpracování PHP skriptů, a tím ulevit serveru hostitele od zbytečné práce ve prospěch užitečnějšího...

Místo dvojitých uvozovek používejte jednoduché uvozovky

Faktem je, že text uzavřený do dvojitých uvozovek je procesorem skenován na přítomnost proměnných a také mnemotechnických substitucí (například \n pro vložení znaku nového řádku do textu).

print("Toto je úplně normální text, ale procesor PHP v něm před výstupem prohledá proměnné a mnemotechnické substituce. Pokud je takový řádek dostatečně dlouhý, tento proces zabere značné množství času.");

Pokud je text uzavřen v jednoduchých uvozovkách, pak jej PHP interpret poslušně zobrazí v původní podobě, aniž by vůbec přemýšlel o tom, že by v něm něco hledal. To trvá mnohem méně času než v předchozím příkladu.

print("Procesor PHP bude velmi šťastný, když uvidí řetězec uzavřený v jednoduchých uvozovkách. A jak se nemůžete radovat - není třeba dělat zbytečnou práci!");

Řetězce tohoto typu lze přirozeně použít nejen ve funkcích, ale také v proměnných.

$string="Jaké požehnání je neanalyzovat tento řádek znovu!";

Nedávejte proměnné do uvozovek

Velmi často vidíte podobný obrázek.

print("Procesoru PHP trvalo $time sekund zpracování této stránky.");

Poté, co jsem se naučil svou předchozí radu a věděl, že pro interpreta PHP je mnohem snazší „slepit“ řetězce dohromady, než v nich skenovat proměnné a nahradit je řetězci odpovídajícími těmto proměnným, není těžké uhodnout, že můj předchozí příklad je příkladem neefektivního využívání zdrojů serveru. Nyní potěšme server optimalizovaným skriptem.

print("Procesor PHP, užívající si života, zpracoval tento skript za ".$time." sekund.");

Pro ty v nádrži: čáry jsou spojeny pomocí tečky (.), tzn

print("Adresa tohoto webu je http://".$_SERVER["HTTP_HOST"]."/!");

zobrazí text „Adresa tohoto webu je http://argon.com.ru/!“

Použijte minimum proměnných

Vždy si musíte pamatovat, že jakákoli globální proměnná je uložena v paměti po celou dobu trvání skriptu! Jako příklad zesměšňování serveru uvedu následující kód.

Otázkou je, proč bychom sakra měli zabírat další paměť a plýtvat zátěží serveru?... Je mnohem efektivnější to udělat tímto způsobem.

print("Procesor PHP rád vypisuje řádky jako je tento.");

Pokud je tedy řetězec použit méně než dvakrát, přiřazení proměnné hodnoty tohoto řetězce je škodlivé.

Používejte krátké názvy proměnných

Pokud skript používá proměnné s nepřiměřeně dlouhými názvy, zatížení serveru se přirozeně zvyšuje.

$windows_xp_edition="Professional";
$windows_xp_build="2600";
$windows_server2003_edition="Standardní";
$windows_server2003_build="3200";

Ale neměli byste ani dávat příliš lakonická jména - v budoucnu si při úpravě scénáře působivé velikosti stokrát vzpomenete na matku jeho tvůrce, a ne láskyplným slovem :)

$ifa="Professional";
$ifb="2600";
$ifc="Standardní";
Sifd="3200";

Nejlepší možností je dát lakonické, ale srozumitelné názvy, nepřesahující osm znaků.

$wxped="Professional";
$wxpbld="2600";
$ws2k3ed="Standardní";
Sws2k3bld="3200";

Používejte vnořené funkce

Takové věci vidíte velmi často.

$string=str_replace("\n"," ",$string);
$string=str_replace("\r"," ",$string);
$string=trim($string);
$string=stripslashes($string);
$string=nasekat($string);
$string=substr($string,0,1024);
print($string);

$string))))),0,1024));

Souhlasím, vypadá to děsivě, ale je zde patrný nárůst produktivity! Je velmi snadné udělat takovou věc, pokud začnete od konce a pokaždé dosadíte odpovídající hodnotu za proměnnou...

Používejte vestavěné funkce

Dovolte mi uvést jednoduchý příklad skriptu, který nahradí všechny speciální znaky HTML jejich odpovídajícími mnemotechnickými substitucemi.



$string=str_replace("<","<",$string);
$string=str_replace(">"",">",$string);
print($string);

Totéž lze dosáhnout, pokud použijete tento kód.

print(htmlspecialchars($string));

Vypadá lépe, váží méně a výrazně snižuje zátěž serveru, zejména při zpracování dlouhých řetězců.

Ještě jeden příklad. Pomocí tohoto skriptu můžete číst obsah textového souboru do pole.

$fp=fopen("database.txt","r");
while($array=fgets($fp,1024));
fclose($fp);

PHP má ale strašně užitečnou vestavěnou funkci file(), která dělá úplně to samé, ale mnohem rychleji!

soubor("databaze.txt");

Závěr: nikdy nebuďte líní se znovu podívat na referenční knihu funkcí PHP. Jsem si jistý, že tam najdete mnoho nástrojů, které vám (a serveru) usnadní život.

Používejte své vlastní funkce

Často je nutné zpracovat několik řádků pomocí přesně stejného algoritmu. Tohle dělají nezkušení programátoři...

print(substr(chop(stripslashes(trim(str_replace("\r"," ",str_replace("\n"," ", $string1))))),0,1024));
print(substr(chop(stripslashes(trim(str_replace("\r"," ",str_replace("\n"," ", $string2))))),0,1024));

A zkušení půjdou jednodušší cestou.

formát funkce(&$string)(

}
print(format($string1));
print(format($string2));

Tímto způsobem můžete provést stejnou akci několikrát, s minimálním zatížením serveru.

Nevytvářejte zbytečné funkce

Pokud například poměrně zkušený programátor zapomene nebo o existenci vestavěné funkce, kterou potřebuje, ani neví, může si ji snadno napsat sám.

funkce optimalizovat(&$string)(
$string=str_replace("&","&",$string);
$string=str_replace(""",""",$string);
$string=str_replace("<;","<",$string);
$string=str_replace(">"",">",$string);
}
print(optimize($string));

Ale vystačíte si s jednoduššími prostředky.

print(htmlspecialchars($string);

Nepoužívejte zbytečné funkce

Zde je příklad neefektivního kódu.

print("Můj strýc");
print("okradl ty nejčestnější...");

Dá se ale velmi snadno optimalizovat.

print("Můj strýc "."nejčestnější pravidla...");

Cítíte ten rozdíl? Věřte mi, že hostitel vám v tomto případě bude vděčný pouze za uvolněné zdroje serveru...

Používejte funkce moudře

Například tento skript.

print(ereg_replace("normal","unhappy",$string));

Povolí algoritmus zpracování regulárního výrazu (POSIX), kde není vůbec vyžadován. A server je zatížen mnohem více. Jeho osud ale můžete usnadnit nahrazením nenasytné funkce jednou méně chtivou po zdrojích.

print(str_replace("unhappy","happy",$string));

Psovodem příliš netahejte

Je známo, že vše, co je obsaženo mimo značku kódu PHP, není zpracováváno procesorem PHP, ale pouze přenášeno beze změny. Někteří lidé to takto používají.

...záhlaví stránky...
print($title);
?>
…navigace…

?>
...zápatí stránky...

Vstup do a opuštění režimu zpracování PHP však zatěžuje server více, než kdyby byl použit tento.

print("...záhlaví stránky...".$title."...navigace...");
include("dynamický obsah");
print("...patička stránky...");
?>

Pokračování příště

Zatím jsem pokryl jen malou část ledovce optimalizace PHP. Je možné, že dodržování jedné rady nepřinese znatelné zvýšení produktivity, ale společné dodržování všech těchto základních pravidel programátorské zdvořilosti výrazně sníží zatížení serveru a zvýší vaši autoritu.

Máte-li jakékoli dotazy nebo návrhy, kontaktujte nás.

Hodně štěstí s optimalizací!

Existuje řada pravidel, která by měla být dodržována pro zvýšení rychlosti PHP aplikací. Pravidla jsou jednoduchá a nebudou vyžadovat výrazné změny stávajících aplikací.

Fastcgi

FastCGI je jednou z možností připojení PHP k webovému serveru. Nejlépe se používá ve spojení s Nginx. PHP-fpm (kontejner Fastcgi pro PHP) a Nginx standardně spolupracují a lze je velmi snadno konfigurovat.

OpCache


Jak se obvykle spouští PHP skript? PHP otevře soubor kódu, zkompiluje jej a poté spustí. Protože souborů může být mnoho, proces jejich otevírání, čtení a kompilace může zabrat mnoho zdrojů. Pokud se soubory nezmění, pak průběžná kompilace nemusí být nutná. Je lepší to udělat jednou a výsledek uložit do mezipaměti.

Přesně to dělá modul opCache. Výsledek první kompilace se uloží do mezipaměti, se kterou bude PHP pracovat. Urychlí tedy provádění odstraněním náročného procesu kompilace. Když se soubory změní, modul sám resetuje mezipaměť a zajistí rekompilaci. Stručně řečeno, tento modul je velmi užitečným šetřičem zdrojů. A to bez nutnosti konfigurace.

Ve verzi PHP5.5+ je tento modul standardně dodáván. V předchozích verzích musí být modul instalován samostatně. Dostupnost můžete zkontrolovat takto: php -i | grep opcache

# Prázdný výstup znamená, že zde není žádný modul

Pokud je verze příliš stará, je lepší použít APC: apt-cache search php-apc

# Toto je alternativa k opCache, ale dělá to samé

Ukládání do mezipaměti

Často je kód prostě pomalý. Například:

  • volání externích API
  • těžký výběr databází
  • zpracování velkých souborů
session.save_handler = memcache session.save_path = "tcp:// localhost:11211"

# localhost:11211 je výchozí hostitel a port Memcache

Toto schéma úložiště vám navíc umožní škálovat na více serverů.

Optimalizace kódu

OOP

Pamatovat si! OOP je vždy pomalý. Objekty je potřeba vytvořit, někde uložit a zničit. Nepoužívejte předměty, pokud je nepotřebujete. Například zde:

set_title($_GET["title"]); $post->set_description($_GET["popis"]); $post->save();

# $posts = seznam objektů Post nějakým způsobem získaných foreach ($posts jako $post) ( echo $post->title . "
"; }

# Seznam objektů používáme pouze k zobrazení vlastnosti

V těchto příkladech použití OOP nedává moc smysl. Ale plýtvá zdroji. Zkuste použít pole, když objekty nejsou potřeba:

$_GET["title"], "description" => $_GET["description"]]);

# Funkce se vyhnula vytvoření objektu, jednoduše uloží data z pole do databáze

"; }

# Mnohem lepší - proveďte jednoduchý výběr a vytiskněte potřebná data z pole

Malé věci

Při práci se soubory používejte absolutní cesty. Pak nedojde ke zbytečným operacím vyhledávání souborů:

zahrnout "/var/www/file.php"; file_get_contents("/var/www/dir/data.txt");

Konstanty třídy fungují efektivněji než definují:

příspěvky ve třídě ( const PER_PAGE = 10; ... )

Nepoužívejte funkce v klauzuli for, protože budou se opakovat při každé iteraci cyklu:

$max = mysql::get_col("SELECT počet(*) FROM příspěvků"); pro ($i = 0; $i< $max; $i++) { ... }

Vždy používejte řetězce jako klíče pole s uvozovkami:

$post["title"] = "První příspěvek";

Kdykoli je to možné, používejte místo regulárních výrazů vestavěné řetězcové funkce.

strpos($post["title"], "dobré");

Použijte řetězce s jednoduchými uvozovkami:

$post["title"] = "V tomto případě nedochází k žádnému dalšímu zpracování proměnných"

PHP cron skripty

Když se PHP používá k vývoji skriptu, který bude spouštět cron, je třeba se vyhnout použití globálních proměnných. Například:

(.+?)<\/title/", $rss, $ odpovídá); }

(.+?)<\/title/", $rss); if ($has_something) $aktualizace= čas(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $aktualizace= čas(); )

Nyní proměnná $updates poroste na maximální limit. Po dosažení limitu paměti bude skript zastaven. Je poměrně obtížné sledovat všechny proměnné, takže je lepší používat funkce. Všechny proměnné vytvořené uvnitř funkce budou po jejím dokončení smazány:

proces(); function process() ( $rss = file_get_contents("http://somesite.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates = time(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates = time(); }

Nejdůležitější

  • Ujistěte se, že používáte opCache pro PHP. Tento zdarmašetří zdroje.
  • Použijte FastCGI (Nginx + PHP-fpm je nejlepší).
  • Funkce v úlohách cron pomohou vyhnout se únikům paměti.
  • Ukládání pomalých částí kódu do mezipaměti je často nejjednodušším řešením, jak věci urychlit.
  • Vzpomeňte si na
  • Jak optimalizovat web a zrychlit jeho výkon?
  • Jakou rychlostí bude stránka fungovat a může fungovat, v souladu s technologiemi, na kterých bude spuštěna?
  • Jaké technologie byste měli použít při nastavování serveru nebo VPS?

Typický problém:
V určitém okamžiku se stránka začne otevírat a fungovat příliš pomalu. Stává se, že hostingová společnost zablokuje web kvůli překročení zátěže nebo nadměrnému využívání zdrojů. Co v takové situaci dělat?

Je možné, že se stránka stala příliš navštěvovanou, nebo byl nainstalován nějaký modul náročný na zdroje, probíhá útok nebo je stránka infikována virem. Tak či onak, všechny tyto případy mají něco do sebe a to je problém všech webů na všech hostingech.

A pokud mluvíme o serverech pro PHP, pak takovým problémem je způsob provádění PHP kódu, stejně jako další významná nastavení prostředí na serveru.
Bez ohledu na to, zda je ve vašem kódu problém nebo ne, zda máte vysoký provoz nebo ne, hodně záleží na nastavení serveru. Aby vše řečené neznělo jako prázdná slova, vznikl tento článek.

V této recenzi otestuji nově nainstalovaný web na jednom z nejběžnějších enginů pro správu obsahu Drupal 7.33.

Pro test byla vybrána pouze jedna komponenta PHP hostingu. Budeme testovat webové servery Nginx A Apache2, moduly mod_php A php-fpm, verze php php53 A php56, podívejme se, jak ovlivňují optimalizátory apc A opcache na rychlosti webu.


Tyto parametry jsou samozřejmě pouze částí nastavení, na kterých závisí rychlost webu. Ale my schválně
Na to se omezujeme, aby recenze nebyla nekonečná.

Vzhledem k tomu:
  • Operační systém Centos 6.7
  • Databázový server: MariaDB 10.21
  • Všechny relace webu jsou uloženy v memcache, aby se odstranil vliv rychlosti instalace relace na rychlost webu.
  • Ve všech testech slouží jako frontend webový server nginx 1.93. V případě Apache2 funguje Nginx jako balancer a také pro statické doručování. V konfiguracích bez použití Apache2 je přímým webovým serverem Nginx
  • Konfigurace Nginx a MariaDB obsahují mnoho optimalizací zaměřených na dosažení maximálního výkonu, ale pro všechny účastníky testu jsou tato nastavení stejná, a proto je třeba jejich dopad ignorovat
  • Parametry opcache a apc jsou převzaty z doporučení Bitrix, protože jsou optimální a univerzální pro většinu webů
Jak budeme testovat?

V místní síti je zabbix server a jeho úkoly každou minutu:

  • Otevřete hlavní stránku testovaného webu, počkejte na určitý obsah na stránce a ujistěte se, že odpověď ze serveru je kód 200.
  • Dalším krokem je autorizace do oblasti pro správu webu, to se provádí odesláním příslušného požadavku POST. Ověření textu a kódu odpovědi na stránce s poskytnutým standardem. Tento krok se týká téměř všech subsystémů webového serveru a jeho rychlost do značné míry závisí na rychlosti interakce s databází
  • Posledním krokem je opustit oblast pro správu webu a zkontrolovat kód odpovědi a text na výstupní stránce
  • Na základě výsledků každého kroku zabbix pečlivě změří a zaznamená rychlost vykreslování php kódu do html, který je srozumitelný prohlížeči, a ukáže nám grafy získaných výsledků
  • Pro každý subjekt budou zaznamenávány hodnoty po dobu jedné hodiny a výsledkem budou průměrné hodnoty za tuto hodinu.
  • Testování bude probíhat v rámci lokální sítě, takže rychlost internetového připojení neovlivní výsledek.
  • Pro usnadnění vnímání uvádím všechny výsledky ve vzestupném pořadí. Tito. úplně první výsledek je nejpomalejší. Všem konfiguracím bylo přiřazeno podmíněné číslo, což vám umožní lepší orientaci ve výsledcích
  • Horní grafy ukazují rychlost generování kódu, čím vyšší hodnota, tím lépe. Nižší grafy představují dobu odezvy serveru a čím nižší hodnota, tím lépe
  • Testované weby si žijí vlastním životem, provádějí pravidelné operace s databázemi a provádějí naplánované úkoly, a proto může mít křivka na grafech vzestupy a pády

Testování:

1. Nginx + php-fpm56 bez optimalizátoru opcache

Z hlediska architektury se jedná o jednu z nejpokročilejších možností. Z hlediska výkonu je to největší zklamání.

Výkon ponechává mnoho přání, ale tato možnost snese zátěž mnohem lépe než možnost č. 2 s Apache2. Tato možnost také využije RAM mnohem efektivněji.

2. Apache2 + mod_php53 bez optimalizátoru apc

Nejtypičtější varianta pro hosting. Tuto možnost využívá 90 % populárních poskytovatelů hostingu. Přestože php53 již dlouhou dobu vývojáři nepodporují, na internetu je spousta stránek, které na této verzi stále fungují.

Tato možnost je nejen velmi pomalá, ale také rychle spadne při nízké zátěži kvůli nedostatku pracovních procesů Apache2 nebo kvůli nedostatku paměti RAM na serveru.

3. Balancování a statika přes Nginx, dynamická část Apache2 + mod_php56 bez optimalizátoru opcache

Tato možnost byla vytvořena jako řešení pro moderní webové stránky. Nabízejí ho hostingové společnosti, které se snaží poskytovat nejnovější verzi PHP. Podle všeobecného přesvědčení by tato verze PHP měla být rychlejší a bezpečnější než předchozí.

Bohužel ne všechny weby mohou s touto verzí plně fungovat. Téměř každá nová verze PHP přestává podporovat některé zastaralé a „nebezpečné“ funkce, čímž narušuje funkčnost „starého“ kódu.
Samotné PHP56 bez optimalizátoru je poměrně pomalé a mod_php má tendenci padat a zabírat veškerou paměť na serveru při zatížení.

4. Nginx + php-fpm53 bez optimalizátoru apc

Docela pokročilá konfigurace pro ty, kteří nechtějí mít problémy kvůli chybám s optimalizátorem kódu. V tomto případě se použije „kompatibilní“ verze PHP interpretu a z balíčku se odstraní Apache2 náročný na zdroje.

5. Balancování a statika přes Nginx, dynamická část Apache2 + mod_php53 + apc

Další běžná variace. Mnoho hostitelských webů jej používá, a to buď ve výchozím nastavení, nebo dává příležitost povolit optimalizátor na svých ovládacích panelech.
Obvykle je Apache2 ponechán na zpracování pravidel .htaccess, jako je překlad odkazů a CNC.

Získáme 3,5násobné zvýšení rychlosti ve srovnání s možností bez použití optimalizátoru.
Samotný Apache (pomocí vlastního modulu mod_php) využívá k provozu mnohem více zdrojů než možnost php-fpm. Apache2 má tendenci spadnout, pokud jeden z jeho modulů selže nebo zaplní RAM celého serveru.

6. Nginx + php-fpm53 + apc

Výborná volba pro weby na starších enginech, které nevyžadují složitý .htaccess

Přesně tuto možnost využívám, když potřebuji upgradovat zastaralý web, získat jej pro dosažení uspokojivé rychlosti a spolehlivého provozu při vysoké zátěži.

7. Balancování a statika přes Nginx, dynamická část Apache2 + php-fpm53 + apc

Možnost pro starší weby se složitým .htaccess. Například staré instalace Bitrixu.

To je ideální pro zastaralé weby. Tato konfigurace je odolná vůči vysokému zatížení, kompatibilní a poměrně produktivní.
Skvělé, když potřebujete pravidla .htaccess a další moduly Apache2.
Mezi nedostatky patří zastaralá a neaktualizovaná verze php, ale pokud není na výběr, je to nejlepší volba. Skvělé pro staré verze Bitrix, Joomla a další běžné CMS, ne pro nejnovější verze.

8. Balancování a statika přes Nginx, dynamická část Apache2 + mod_php56 + opcache

Docela produktivní, ale na zdroje náročná konfigurace se všemi nedostatky mod_php.

Poměrně rychle, ale při zatížení může serveru dojít paměť a rychlost výrazně klesne.

9. Nginx + php-fpm56 + opcache

Nejproduktivnější možnost.

Toto je nejlepší volba pro všechny moderní weby. Dobře drží zátěž a vykazuje nejlepší výsledky z hlediska výkonu. Přesně tuto možnost používám, když je úkolem optimalizovat výkon webu a zvýšit jeho rychlost.
Jedinou nevýhodou je, že nebudeme moci používat .htaccess a všechna pravidla mod_rewrite je třeba přepsat do syntaxe Nginx.
Moduly Apache2 také nebudou fungovat. Pokud jsou použity, pak tato možnost nebude fungovat.

10. Balancování a statika přes Nginx, dynamická část Apache2 + opcache php-fpm56+

Nejlepší volba pro weby, kde je potřeba .htaccess. Ideální pro nejnovější verze Bitrix.

Dobře drží zátěž díky php-fpm. Tuto možnost aktivně využívám u většiny webů.

Domovská stránka testovacího webu
Číslo konfigurace Architektura Průměrná odezva ms.
1 77,04 103,6
2 78,79 103,98
3 78,85 102,38
4 81,55 97,88
5 Apache2 + mod_php53 + apc 303,37 29,36
6. Nginx + php-fpm53 + apc 312,33 24,73
7. Apache2 + php-fpm53 + apc 339,63 23,32
8. 484,96 16,91
9. Nginx + php-fpm56 + opcache 546,34 14,08
10. Apache2 + php-fpm56+ opcache 571,14 13,78
Autorizace v administračním panelu testovacího webu
Číslo konfigurace Architektura Průměrná rychlost stahování kb. Průměrná odezva ms.
1 Nginx + php-fpm56 bez optimalizátoru opcache 67,51 239,01
2 Apache2 + mod_php53 bez optimalizátoru apc 64,61 257,51
3 Apache2 + mod_php56 bez optimalizátoru opcache 66,75 242,42
4 Nginx + php-fpm53 bez optimalizátoru apc 68.79 233.15
5 Apache2 + mod_php53 + apc 173,81 94,26
6. Nginx + php-fpm53 + apc 173,3 91,3
7. Apache2 + php-fpm53 + apc 182,1 90,5
8. Apache2 + mod_php56 + opcache 218,35 77,55
9. Nginx + php-fpm56 + opcache 252,83 62,25
10. Apache2 + php-fpm56+ opcache 262,8 60,85
Odhlášení z administračního panelu testovacího webu
Číslo konfigurace Architektura Průměrná rychlost stahování kb. Průměrná odezva ms.
1 Nginx + php-fpm56 bez optimalizátoru opcache 41,01 184,49
2 Apache2 + mod_php53 bez optimalizátoru apc 42,42 188,97
3 Apache2 + mod_php56 bez optimalizátoru opcache 42,06 188,37
4 Nginx + php-fpm53 bez optimalizátoru apc 45,48 169,15
5 Apache2 + mod_php53 + apc 190,1 41,87
6. Nginx + php-fpm53 + apc 185,92 41,24
7. Apache2 + php-fpm53 + apc 202,78 39,21
8. Apache2 + mod_php56 + opcache 315,56 26,23
9. Nginx + php-fpm56 + opcache 373,19 20,43
10. Apache2 + php-fpm56+ opcache 381,21 20,57

Jako shrnutí:

  • V reálném životě mohou být všechny možnosti s Apache2 pomalejší, protože v mých testech jsem záměrně přenesl statický výstup do Nginx. To bylo provedeno za účelem eliminace vlivu statické výstupní rychlosti na výsledky měření rychlosti PHP interpretu. Jednou z nejslabších stránek Apache2 a zároveň silnou stránkou Nginx je rychlost statického výstupu. To je patrné zejména při vysokém zatížení. Kromě toho je Nginx méně náchylný k útoku „pomalého připojení“.
  • mod_php velmi rychle zabírá veškerou dostupnou paměť serveru a při zatížení ztrácí výkon
  • php-fpm využívá paměť mnohem efektivněji, bezpečněji a flexibilněji v nastavení. V některých případech je rychlejší a bez velkého zatížení.
  • Test má úzkou specifičnost, zde jsme viděli zvláštnosti Drupal enginu, ostatní se mohou chovat jinak, ale obecný trend bude stejný.

A co je nejdůležitější, rychlost vašeho webu závisí na konfiguraci vašeho serveru nebo hostingu. Výběrem správné architektury můžete dosáhnout pětinásobného zvýšení rychlosti webu.

Pokud máte nějaké dotazy, potíže nebo potřebujete poradit:
Moje kontakty v

Od autora: Každý seberespektující vývojář se obává o „osud“ svého kódu. Snaží se, aby aplikace byla co nejpohodlnější, rychlejší a zvýšila její odolnost proti chybám. Ne vždy vám ale optimalizace PHP umožní dosáhnout těchto výšin.

Neléč si ruku, když ti kulhá noha!

Omlouvám se za irský lidový aforismus! Ale dokonale odráží podstatu problému. Optimalizace kódu vám nejčastěji neumožní zlepšit výkon vytvořeného skriptu nebo prostředku. A v případě , se vše extrémně komplikuje kvůli velkému množství faktorů, které vy (jako vývojář) prostě neovlivníte.

Pokud jde o jevy, které nemůžeme ovlivnit, mám na mysli rychlost připojení k internetu, zatížení serveru, nastavení operačního systému na klientském počítači a výkon hardwaru počítače uživatele. Všechny tyto složky nebudete moci ovlivnit. A nakonec se ukáže, že optimalizace kódu PHP nedá úplný výsledek.

Co zůstává pod kontrolou webového vývojáře:

Nastavení serveru jsou omezená. Nastavení parametrů prostřednictvím konfiguračního souboru Apache httpd.conf umožňuje nastavit počet podřízených procesů, časový limit připojení soketu, velikost výstupní vyrovnávací paměti pro připojení TCP/IP, dobu nečinnosti a další.

Nastavení jazykového jádra - prostřednictvím parametrů uvedených v souboru php.ini. Umožňuje nastavit hodnoty vyrovnávací paměti, změnit maximální dobu provádění skriptu, zpracování chyb, správu protokolů a další nastavení.

Použití optimalizace obrazu PHP – o tom později. Optimalizace programového kódu - umožňuje „ušetřit“ zdroje a zvýšit výkon.

Například musíte vědět, že echo je rychlejší než tisk. Po ladění je lepší vypnout chybové zprávy, abyste ušetřili zdroje. Místo zřetězení řetězců použijte echo. Objekty a metody třídy () zabírají hodně paměti.

Práce s obrázky

Nejsem příznivcem zpracování obrazu na straně serveru. To také vede k plýtvání drahocennými zdroji, kterých je hosting vždy nedostatek. Ukazuje se, že ušetřením na jedné věci plýtváme dalšími „rezervami“.

Optimálnější možností je nahrát obrázky do služby třetí strany, odkud se načtou v optimalizované podobě do prohlížeče uživatele na dané adrese. Takových služeb je na internetu mnoho. Chci jmenovat jen některé z nich: kraken.io, TinyPNG

Jak vidíte, znalost optimalizace pro vyhledávače v PHP je důležitá i pro profesionální vývojáře.

Navíc má vlastní vestavěné nástroje pro „zesvětlení“ obrázků. Například funkce imagecopyresampled(). Snižuje váhu obsahu převzorkováním a změnou velikosti obrázku. Příklad použití:

header("Typ obsahu: obrázek/jpeg");

$soubor = "ukazka.jpg" ;

$img_obrabot = imagecreatetruecolor(200, 100);

$img_orig = imagecreatefromjpeg($file);

imagecopyresampled($img_obrabot, $img_orig, 0, 0, 0, 0, 200, 100, 541, 286);

imagejpeg ($img_obrabot) ;

Co jiného můžete dělat?

Nezapomeňte také použít optimalizaci na straně klienta pomocí PHP. Server může do určité míry ovlivnit klientský prohlížeč prostřednictvím Cache-Control a také atributy této hlavičky: post-check, max-age a další.

Hlavičky Last-Modified a ETag navíc umožňují spravovat stav mezipaměti na klientském počítači. Nastavují jedinečné ID pro úpravu každého souboru. Díky tomu server znovu neposílá zdroje, ale pouze odpovídá se stavem 304.

V článku jsme se nezabývali otázkou optimalizace pomocí PHP FPM. Ale zvážit to bude vyžadovat samostatný článek. To je pro dnešek vše. Do příště!

Tématem tohoto článku je fakt, že použití FastCGI v PHP nezrychlí dobu načítání PHP kódu oproti např. mod_php.

Většina tradičních webových programovacích jazyků (Perl, Ruby, Python atd.) podporuje psaní skriptů, které pracují v takzvaném „režimu FastCGI“. Navíc například Ruby on Rails nelze v režimu CGI použít vůbec, protože tráví desítky sekund propojováním všech svých četných knihoven.

Níže budu hovořit o metodě, která v některých případech umožňuje zrychlit načítání objemného PHP kódu více než 20krát, bez vedlejších účinků nebo výrazných nepříjemností. Nejprve si ale řekněme základy...

Co je FastCGI?

Nejprve si povíme něco o tom, čemu se říká „klasické“ FastCGI, které se používá v C, Perlu, Ruby atd. V PHP má FastCGI své vlastní charakteristiky, podíváme se na ně o něco později. Nyní mluvíme o non-PHP.

FastCGI funguje takto: skript se načte do paměti, spustí nějaký těžký inicializační kód (například včetně velkých knihoven) a poté vstoupí do smyčky zpracovávající příchozí požadavky HTTP. Stejný proces skriptu zpracovává několik různých požadavků jeden po druhém, což se liší od práce v režimu CGI, kdy je pro každý požadavek vytvořen samostatný proces, který po dokončení zpracování „umírá“. Obvykle po zpracování N požadavků skript FastCGI skončí, takže jej server znovu restartuje v „čisté karanténě“.

Pro urychlení zpracování se samozřejmě nespouští jeden proces skriptu, ale několik najednou, aby každý další požadavek nečekal na zpracování předchozího. V konfiguraci serveru lze nastavit jak počet současně spuštěných procesů, tak počet sekvenčních požadavků na proces.

Staré skripty napsané s ohledem na CGI je potřeba upravit, aby mohly fungovat v prostředí FastCGI (platí pro použití FastCGI v C, Perlu atd.; v PHP není potřeba žádná úprava, ale má to své nevýhody, viz níže) . Ve skutečnosti dříve skript začínal pokaždé „od nuly“, ale nyní se musí vypořádat s „odpadky“, které zbyly z předchozího požadavku. Pokud dříve vypadal CGI skript v Perlu

useSomeHeavyLibrary; tisknout "Ahoj světe!\n";

pak po úpravě pro FastCGI to vypadá jako něco podobného

useSomeHeavyLibrary; while ($request = get_fastcgi_request()) ( tisk "Ahoj, světe!\n"; )

Výsledkem je úspora rychlosti odezvy: vždy, když přijde požadavek, skript nemusí spouštět „těžký“ inicializační kód knihovny (někdy to trvá desítky sekund).

FastCGI má významnou nevýhodu: nový požadavek se začne zpracovávat nikoli v „čistém“ prostředí, ale v prostředí, které zůstalo „z minula“. Pokud má skript úniky paměti, postupně se hromadí, dokud nespadne. Totéž platí pro zdroje, které zapomněli uvolnit (otevřené soubory, databázová připojení atd.). Je tu ještě jedna nevýhoda: pokud se kód skriptu změnil, musíte o tom nějak informovat server FastCGI, aby „zabil“ všechny své procesy a začal znovu.

Ve skutečnosti technika „jednou iniciovat, zpracovat mnoho požadavků“ funguje nejen ve FastCGI. Jakýkoli server napsaný ve stejném jazyce jako skript běžící pod ním jej implicitně používá. Například server Mongrel je napsán celý v Ruby právě proto, aby pod ním bylo možné rychle spustit Ruby On Rails. Server Apache Tomcat, napsaný v Javě, rychle spouští Java servlety, protože... nevyžaduje jejich reinicializaci. Technologie mod_perl je také založena na skutečnosti, že kód Perl není mezi požadavky vykládán, ale zůstává v paměti. Všechny tyto servery mají samozřejmě stejné problémy s nepředvídatelností, úniky paměti a potížemi s restartováním jako aplikace FastCGI.

Proč FastCGI nezrychluje PHP

Pravděpodobně jste slyšeli, že PHP lze provozovat i v režimu FastCGI a že to dělá mnoho vysoce zatěžovaných projektů (Mamba, některé projekty Mail.Ru atd.). To údajně poskytuje „významné zvýšení“ výkonu, protože (podle pověstí) FastCGI šetří čas na inicializaci skriptu a začlenění knihovny.

Nevěřte tomu! Ve skutečnosti je podpora FastCGI PHP čistě nominální. Přesněji, neposkytuje výhody v tom smyslu, v jakém se používá ke zkrácení doby inicializace skriptu. Samozřejmě můžete spustit PHP FastCGI server a dokonce s ním přímo pracovat nginx nebo lighttpd, ale zrychlení, které získáte při načítání kódu, bude nulové. Těžké knihovny PHP (například Zend Framework) se v režimech mod_php nebo CGI načítaly dlouho a v režimu FastCGI se budou načítat ještě dlouhou dobu.

Vlastně to není překvapivé: koneckonců, abyste mohli spustit jakýkoli PHP skript v režimu FastCGI, nemusíte jej upravovat. Ani jeden řádek změněného kódu! Když jsem se poprvé rozhodl experimentovat s FastCGI v PHP, strávil jsem několik hodin hledáním informací na internetu, jak přesně upravit kód PHP, aby jej optimálně spouštěl v režimu FastCGI. Prošel jsem veškerou dokumentaci k PHP a několik desítek vývojářských fór PHP, dokonce jsem se podíval na zdrojový kód PHP, ale stále jsem nenašel jediné doporučení. Vzhledem k předchozí zkušenosti s FastCGI v Perlu a C jsem byl neuvěřitelně překvapen. Vše však zapadlo, když se ukázalo, že není potřeba kód měnit, a přestože se v rámci jednoho FastCGI procesu zpracovává několik spojení, PHP interpret se inicializuje pokaždé znovu (na rozdíl od „klasického“ FastCGI). Navíc se zdá, že většina PHP vývojářů, kteří s radostí používají FastCGI+PHP, si ani neuvědomuje, že by to mělo fungovat jinak...

eAccelerator: Zrychlení načítání kódu PHP

Pokaždé, když PHP skript obdrží řízení, PHP zkompiluje (přesněji přeloží) kód skriptu do interní reprezentace (bytecode). Pokud je soubor malý, dojde k překladu velmi rychle (Zend Engine v PHP je jedním z lídrů v rychlosti překladu), pokud však zahrnuté knihovny „váží“ několik megabajtů, překlad se zpozdí.

Existuje řada nástrojů, které ukládají přeloženou interní reprezentaci kódu PHP do sdílené paměti. Když je tedy soubor PHP znovu povolen, již se nepřekládá a bajtový kód se přebírá z mezipaměti v paměti. To samozřejmě výrazně urychluje práci.

Jedním z takových nástrojů je eAccelerator. Instaluje se jako rozšíření PHP (připojené v php.ini) a vyžaduje velmi minimální konfiguraci. Doporučuji povolit režim cachování bytecode výhradně v RAM a vypnout kompresi (nastavit parametry eaccelerator.shm_only=1 a eaccelerator.compress=0). Nainstalujte a nakonfigurujte také ovládací panel control.php, který je součástí distribuce eAccelerator, abyste mohli sledovat stav mezipaměti v reálném čase. Bez ovládacího panelu bude pro vás velmi obtížné diagnostikovat, pokud eAccelerator z nějakého důvodu nefunguje.

Výhodou eAcceleratoru je, že funguje velmi stabilně a rychle i na velkých objemech PHP kódu. S tímto nástrojem jsem nikdy neměl žádné problémy (například na rozdíl od Zend Accelerator).

“Můj skript spolu s knihovnami zabírá 5 MB, co mám dělat?...”

Myslíte si, že 5 MB kódu je na PHP moc? Nic takového. Zkuste systémy jako Zend Framework a Propel, abyste viděli něco jiného. Celý Zend Framework zabírá asi 5 MB. Třídy generované Propelem jsou také poměrně velké a mohou zabírat několik dalších megabajtů.

Mnoho lidí se na tomto místě zasměje a řekne, že není potřeba používat Zend Framework a Propel, protože... jsou pomalé. Realita je ale taková, že ani nejsou vůbec pomalé... Metoda, která standardně používá PHP k načítání kódu, má špatný výkon. Naštěstí není těžké situaci napravit.

Abych nebyl neopodstatněný, uvedu výsledky malého testu, který jsem konkrétně provedl v „čistém“ prostředí, nevázaném na žádný konkrétní projekt. Byla testována rychlost připojení všech souborů Zend Framework (s výjimkou Zend_Search_Lucene). Všechna volání require_once byla dříve z kódu odstraněna a závislosti byly načteny pouze prostřednictvím mechanismu autoload.

Celkem tedy bylo propojeno 790 PHP souborů o celkovém objemu 4,9 MB. Docela hodně, že? Spojení probíhalo nějak takto:

function __autoload($className) ( $fname = str_replace("_", "/", $className) . ".php"; $result = require_once($fname); return $result; ) // Propojte třídy jeden po druhém jeden v pořadí jejich závislostí. class_exists("Zend_Acl_Assert_Interface"); class_exists("Zend_Acl_Exception"); class_exists("Zend_Acl_Resource_Interface"); class_exists("Zend_Acl_Resource"); // ... a tak dále pro všech 790 souborů

Protože se používá automatické načítání, volání class_exists() přinutí PHP zahrnout příslušný soubor třídy. (Toto je nejjednodušší způsob, jak „vytáhnout“ funkci autoload.) Pořadí připojení jsem zvolil tak, že každá následující třída již měla v době spuštění načteny všechny své závislé třídy. (Tuto objednávku lze snadno stanovit jednoduchým vytištěním hodnoty $fname ve funkci __autoload do prohlížeče.)

Zde jsou výsledky testů s eAcceleratorem a bez něj na mém nepříliš výkonném notebooku (Apache, mod_php):

  • Připojení všech souborů po jednom, eAccelerator deaktivován: 911 ms.
  • Připojení všech souborů jeden po druhém, eAccelerator povolen: 435 ms. 15 M vyrovnávací paměti je obsazeno pro bajtový kód.

Jak vidíte, eAccelerator poskytuje přibližně 2x zrychlení na 790 souborech s celkovým objemem 4,9 MB. Trochu slabý. Navíc 435 ms je zjevně příliš mnoho na skript, který nedělá nic jiného, ​​než že obsahuje knihovny.

Nyní přidáme nějaké steroidy

Říká se, že PHP načítá jeden velký soubor mnohem rychleji než deset malých o stejné celkové velikosti. Rozhodl jsem se toto tvrzení otestovat zkombinováním celého Zend Frameworku do jednoho 4,9 MB souboru a jeho propojením s jediným voláním require_once. Uvidíme, co se stane.

  • Povolení jednoho velkého sloučeného souboru, eAccelerator deaktivován: 458 ms.
  • Povolení jednoho velkého sloučeného souboru, eAccelerator povoleno: 42 ms. Je obsazeno 31 MB mezipaměti bajtového kódu.

První řádek říká, že jeden velký soubor o velikosti 4,9 MB se ve skutečnosti načítá rychleji než 790 malých: 458 ms oproti 911 ms (viz výše). 2x úspora.

Ale druhý řádek mě přiměl překvapením vyskočit na židli a několikrát zkontrolovat výsledek. Doufám, že se vám stane to samé. Ve skutečnosti je 42 ms 11krát rychlejší než s deaktivovaným eAcceleratorem! Ukazuje se, že eAccelerator miluje malé soubory ještě méně (mimochodem i v režimu eaccelerator.check_mtime=0): 11násobná úspora.

Takže jsme ve skutečnosti získali 22x rychlejší časy načítání, jak bylo slibováno v názvu. Dříve trvalo připojení celého Zend Frameworku, rozděleného do souborů, 911 ms a pomocí eAcceleratoru a spojení všech souborů do jednoho - 42 ms. A to není na skutečném serveru, ale jen na obyčejném notebooku.

Závěr: 22krát rychlejší

Pojďme si to shrnout.

  • Sloučení všech souborů do jednoho velkého souboru plus povolení eAccelerator pro tento velký soubor poskytuje 22x zrychlení s velikostí kódu 4,9 MB a počtem 790 souborů.
  • Pro malý počet velkých souborů může eAccelerator poskytnout 10x zrychlení. Pokud existuje mnoho souborů a celkový objem je velký, zrychlení je přibližně 2krát.
  • Spotřeba vyrovnávací paměti závisí na počtu souborů oddílů: pro pevnou velikost platí, že čím více souborů je, tím menší spotřeba.

S tím vším nemá eAccelerator hlavní problémy „skutečného“ FastCGI serveru. Skripty jsou bez úniků paměti a běží v zaručeně „čistém“ prostředí. Také nemusíte sledovat změny kódu a restartovat server pokaždé, když jsou provedeny úpravy více či méně hlubokého kódu systému.

Všimněte si také, že jsme zahrnuli celý Zend Framework. Ve skutečných skriptech bude množství kódu mnohem menší, protože Pro provoz je obvykle zapotřebí pouze malá část ZF. Ale i když knihovny zabírají 4,9 MB, dostaneme dobu načítání 42 ms - což je pro PHP skript docela přijatelné. Ve vytížených projektech totiž mohou PHP skripty fungovat i několik set milisekund (Facebook, My Circle atd.).

Samozřejmě, pokud plánujete spouštět FastCGI v PHP ne z důvodů výkonu, ale jednoduše proto, abyste nebyli svázáni s Apache a omezili se na kombinaci „nginx+PHP“ nebo „lighttpd+PHP“, nic tomu nebrání. Navíc použitím eAccelerator pro FastCGI+PHP a sloučením mnoha kódových souborů do jednoho velkého získáte stejné zrychlení, které jsem popsal výše. Nelichotte si však nadějemi, že zrychlení poskytlo FastCGI: není tomu tak. Pomocí mod_php+eAccelerator byste dosáhli téměř stejného výsledku jako FastCGI+eAccelerator.

Ruční sloučení všech souborů knihovny do jednoho je únavný úkol. Je lepší napsat nástroj, který automaticky analyzuje seznam souborů PHP obsažených ve skriptu, a při příštím spuštění tyto soubory zkombinovat a zapsat do dočasného adresáře (pokud tak již nebylo provedeno) a pak je připojte pomocí require_once. Dnes nechávám napsání takového nástroje (uveďte nebo vezměte podrobnosti) na svědomí čtenáře.

Doporučuji také opustit explicitní zahrnutí souborů pomocí require_once a přepnout na automatické načítání. Jen na to nezkoušejte používat Zend_Loader: je velmi pomalý (podle mých měření bude připojení stovky souborů trvat asi 50 ms navíc). Je lepší napsat si vlastní jednoduchou funkci automatického načítání, která rychle udělá veškerou práci. Automatické načítání vám umožní bezpečně kombinovat více souborů knihovny do jednoho, aniž byste se museli starat o to, jak se vypořádat s manuálním require_onces.

Nakonec použijte funkci set_include_path(), aby kód zahrnutí knihovny vypadal takto:

require_once "Some/Library.php";

vyžadovat_jednou LIB_DIR . "/Some/Library.php";

Konstanty, které výslovně definují cestu do adresáře knihovny, jsou velkým zlem a komplikují program. Také nepřímo odporují standardům kódování Zend Framework a PEAR, které také doporučuji dodržovat, kdykoli je to možné.

Pokud tedy chcete v PHP skriptech používat „těžké“ knihovny, hodně štěstí! PHP je skriptovací jazyk, který vám to skutečně umožňuje bez ohledu na nepříjemnosti FastCGI a problémy „vestavěných“ serverů.