Optimalizácia na strane klienta v PHP. Tipy na optimalizáciu PHP skriptov. Ako budeme testovať

V tomto článku chcem uviesť niekoľko tipov, pomocou ktorých môžete výrazne urýchliť spracovanie PHP skriptov, čím odbremeníte server hostiteľa od zbytočnej práce v prospech užitočnejšieho...

Namiesto dvojitých úvodzoviek používajte jednoduché úvodzovky

Faktom je, že text uzavretý v úvodzovkách procesor skenuje na prítomnosť premenných, ako aj mnemotechnických náhrad (napríklad \n na vloženie znaku nového riadku do textu).

print("Toto je úplne normálny text, ale procesor PHP v ňom pred výstupom skenuje premenné a mnemotechnické substitúcie. Ak je takýto riadok dostatočne dlhý, tento proces zaberie značné množstvo času.");

Ak je text uzavretý v jednoduchých úvodzovkách, interpret PHP ho poslušne zobrazí v jeho pôvodnej podobe bez toho, aby čo i len pomyslel na to, že v ňom niečo hľadá. Trvá to oveľa menej času ako v predchádzajúcom príklade.

print("Procesor PHP bude veľmi šťastný, keď uvidí reťazec uzavretý v jednoduchých úvodzovkách. A ako sa nemôžete tešiť - nie je potrebné robiť zbytočnú prácu!");

Prirodzene, reťazce tohto typu možno použiť nielen vo funkciách, ale aj v premenných.

$string="Aké požehnanie je neanalyzovať tento riadok znova!";

Nedávajte premenné do úvodzoviek

Veľmi často vidíte podobný obrázok.

print("procesoru PHP trvalo spracovanie tejto stránky $time sekúnd.");

Po oboznámení sa s mojimi predchádzajúcimi radami a vedomím, že pre interpreta PHP je oveľa jednoduchšie „zlepiť“ reťazce dohromady, než v nich skenovať premenné a nahradiť ich reťazcami zodpovedajúcimi týmto premenným, nie je ťažké uhádnuť, že môj predchádzajúci príklad je príkladom neefektívneho využívania zdrojov servera. Teraz potešte server optimalizovaným skriptom.

print("Procesor PHP, užívajúci si život, spracoval tento skript za ".$time." sekúnd.");

Pre tých v nádrži: čiary sú spojené pomocou bodky (.), tj

print("Adresa tejto stránky je http://".$_SERVER["HTTP_HOST"]."/!");

zobrazí text „Adresa tejto stránky je http://argon.com.ru/!“

Použite minimum premenných

Vždy si musíte pamätať, že akákoľvek globálna premenná je uložená v pamäti po celú dobu trvania skriptu! Ako príklad zosmiešňovania servera uvediem nasledujúci kód.

Otázkou je, prečo by sme do pekla mali zaberať dodatočnú pamäť a plytvať tak záťažou servera?... Je to oveľa efektívnejšie urobiť to týmto spôsobom.

print("Procesor PHP rád vypisuje takéto riadky.");

Ak sa teda reťazec použije menej ako dvakrát, priradenie premennej hodnoty tohto reťazca je škodlivé.

Používajte krátke názvy premenných

Ak skript používa premenné s neprimerane dlhými názvami, zaťaženie servera sa prirodzene zvyšuje.

$windows_xp_edition="Professional";
$windows_xp_build="2600";
$windows_server2003_edition="Štandard";
$windows_server2003_build="3200";

Nemali by ste však dávať ani príliš lakonické mená - v budúcnosti si pri úprave scenára pôsobivej veľkosti stokrát spomeniete na matku jeho tvorcu a nie láskavým slovom :)

$ifa="Professional";
$ifb="2600";
$ifc="Štandard";
Sifd="3200";

Najlepšou možnosťou je dať lakonické, ale zrozumiteľné mená, ktoré nepresahujú osem znakov.

$wxped="Profesionál";
$wxpbld="2600";
$ws2k3ed="Štandard";
Sws2k3bld="3200";

Použite vnorené funkcie

Takéto veci vidíte veľmi často.

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

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

Súhlasím, vyzerá to hrozne, ale je tu badateľný nárast produktivity! Je veľmi ľahké urobiť takú vec, ak začnete od konca a zakaždým dosadíte zodpovedajúcu hodnotu za premennú...

Použite vstavané funkcie

Dovoľte mi uviesť jednoduchý príklad skriptu, ktorý nahrádza všetky špeciálne znaky HTML ich zodpovedajúcimi mnemotechnickými náhradami.



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

To isté možno dosiahnuť, ak použijete tento kód.

print(htmlspecialchars($string));

Vyzerá krajšie, váži menej a výrazne znižuje zaťaženie servera, najmä pri spracovaní dlhých reťazcov.

Ešte jeden príklad. Pomocou tohto skriptu môžete čítať obsah textového súboru do poľa.

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

Ale PHP má strašne užitočnú vstavanú funkciu file(), ktorá robí presne to isté, ale oveľa rýchlejšie!

file("databaza.txt");

Záver: nikdy nebuďte leniví pozrieť sa ešte raz na príručku funkcií PHP. Som si istý, že tam nájdete množstvo nástrojov, ktoré vám (a serveru) uľahčia život.

Používajte svoje vlastné funkcie

Často je potrebné spracovať niekoľko riadkov pomocou presne rovnakého algoritmu. Toto robia neskúsení programátori...

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 skúsení pôjdu jednoduchšou cestou.

formát funkcie(&$string)(

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

Týmto spôsobom môžete vykonať rovnakú akciu niekoľkokrát, s minimálnym zaťažením servera.

Nevytvárajte zbytočné funkcie

Ak napríklad pomerne skúsený programátor zabudne alebo o existencii vstavanej funkcie, ktorú potrebuje, ani nevie, môže si ju jednoducho napísať sám.

optimalizácia funkcie(&$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 jednoduchšími prostriedkami.

print(htmlspecialchars($string);

Nepoužívajte zbytočné funkcie

Tu je príklad neefektívneho kódu.

print("Môj strýko");
print("okradli tých najčestnejších...");

Ale dá sa veľmi jednoducho optimalizovať.

print("Môj strýko "."najúprimnejšie pravidlá...");

Cítiš ten rozdiel? Verte mi, že hostiteľ vám bude v tomto prípade vďačný len za uvoľnené zdroje servera...

Používajte funkcie rozumne

Napríklad tento skript.

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

Povolí algoritmus spracovania regulárneho výrazu (POSIX), kde sa to vôbec nevyžaduje. A server je zaťažený oveľa viac. Jeho osud však môžete uľahčiť tým, že nenasytnú funkciu nahradíte jednou menej chamtivou po zdrojoch.

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

Neťahajte manipulátorom príliš

Je známe, že všetko, čo sa nachádza mimo značky kódu PHP, nie je spracovávané procesorom PHP, ale jednoducho prenášané nezmenené. Niektorí ľudia to používajú takto.

...hlavička strany...
print($title);
?>
…navigácia…

?>
...päta strany...

Ale vstup a výstup z PHP spracovateľského režimu zaťažuje server viac, ako keby bol použitý.

print("...hlavička stránky...".$title."...navigácia...");
include("dynamický obsah");
print("...päta strany...");
?>

Pokračovanie nabudúce

Zatiaľ som pokryl iba malú časť ľadovca optimalizácie PHP. Je možné, že dodržiavanie jednej rady nevedie k výraznému zvýšeniu produktivity, ale spoločné dodržiavanie všetkých týchto základných pravidiel zdvorilosti programátora výrazne zníži zaťaženie servera a zvýši vašu autoritu.

Ak máte nejaké otázky alebo návrhy, kontaktujte nás.

Veľa šťastia s optimalizáciou!

Existuje množstvo pravidiel, ktoré by sa mali dodržiavať, aby sa zvýšila rýchlosť PHP aplikácií. Pravidlá sú jednoduché a nebudú vyžadovať výrazné zmeny existujúcich aplikácií.

Fastcgi

FastCGI je jednou z možností pripojenia PHP k webovému serveru. Najlepšie sa používa v spojení s Nginx. PHP-fpm (kontajner Fastcgi pre PHP) a Nginx štandardne spolupracujú a dajú sa veľmi ľahko konfigurovať.

OpCache


Ako sa zvyčajne spúšťa PHP skript? PHP otvorí súbor kódu, skompiluje ho a potom ho spustí. Keďže súborov môže byť veľa, proces ich otvárania, čítania a kompilácie môže zabrať veľa zdrojov. Ak sa súbory nezmenia, nepretržitá kompilácia nemusí byť potrebná. Je lepšie to urobiť raz a výsledok uložiť do vyrovnávacej pamäte.

Presne to robí modul opCache. Výsledok prvej kompilácie sa uloží do vyrovnávacej pamäte, s ktorou bude PHP pracovať. Zrýchli teda vykonávanie odstránením náročného procesu kompilácie. Keď sa súbory zmenia, samotný modul vynuluje vyrovnávaciu pamäť a zabezpečí rekompiláciu. Stručne povedané, tento modul je veľmi užitočným šetričom zdrojov. A to bez nutnosti konfigurácie.

Vo verzii PHP5.5+ je tento modul štandardne dodávaný. V predchádzajúcich verziách musí byť modul nainštalovaný samostatne. Dostupnosť môžete skontrolovať takto: php -i | grep opcache

# Prázdny výstup znamená, že neexistuje žiadny modul

Ak je verzia príliš stará, je lepšie použiť APC: apt-cache search php-apc

# Toto je alternatíva k opCache, ale robí to isté

Ukladanie do vyrovnávacej pamäte

Často je kód jednoducho pomalý. Napríklad:

  • volania externých API
  • ťažké výbery databáz
  • spracovanie veľkých súborov
session.save_handler = memcache session.save_path = "tcp:// localhost:11211"

# localhost:11211 je predvolený hostiteľ a port Memcache

Okrem toho vám táto schéma úložiska umožní škálovať na viacerých serveroch.

Optimalizácia kódu

OOP

Pamätajte! OOP je vždy pomalý. Objekty je potrebné vytvoriť, niekde uložiť a zničiť. Nepoužívajte predmety, ak ich nepotrebujete. Napríklad tu:

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

# $posts = zoznam objektov Post získaných nejakým spôsobom foreach ($posts ako $post) (echo $post->title . "
"; }

# Zoznam objektov používame len na zobrazenie vlastnosti

V týchto príkladoch použitie OOP nedáva veľký zmysel. Ale to plytvá zdrojmi. Skúste použiť polia, keď nie sú potrebné objekty:

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

# Funkcia sa vyhne vytvoreniu objektu, jednoducho uloží údaje z poľa do databázy

"; }

# Oveľa lepšie - urobte jednoduchý výber a vypíšte potrebné údaje z poľa

Malé veci

Pri práci so súbormi používajte absolútne cesty. Potom sa nevyskytnú zbytočné operácie vyhľadávania súborov:

zahrnúť "/var/www/file.php"; file_get_contents("/var/www/dir/data.txt");

Konštanty triedy fungujú efektívnejšie ako definovať:

príspevky v triede ( const PER_PAGE = 10; ... )

Nepoužívajte funkcie v klauzule for, pretože budú sa opakovať pri každej iterácii cyklu:

$max = mysql::get_col("SELECT počet(*) FROM príspevkov"); pre ($i = 0; $i< $max; $i++) { ... }

Vždy používajte reťazce ako kľúče poľa s úvodzovkami:

$post["title"] = "Prvý príspevok";

Vždy, keď je to možné, používajte namiesto regulárnych výrazov vstavané funkcie reťazcov.

strpos($post["title"], "dobre");

Použite reťazce s jednoduchými úvodzovkami:

$post["title"] = "V tomto prípade nejde o žiadne ďalšie spracovanie premenných"

PHP cron skripty

Keď sa PHP používa na vývoj skriptu, ktorý bude spustený cron, je potrebné vyhnúť sa používaniu globálnych premenných. Napríklad:

(.+?)<\/title/", $rss, $zhoduje sa); }

(.+?)<\/title/", $rss); if ($has_something) $aktualizácie= cas(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $aktualizácie= cas(); )

Teraz premenná $updates narastie na maximálny limit. Po dosiahnutí limitu pamäte sa skript zastaví. Je dosť ťažké sledovať všetky premenné, preto je lepšie používať funkcie. Všetky premenné vytvorené vo funkcii budú po jej dokončení vymazané:

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(); }

Najdôležitejšie

  • Uistite sa, že používate opCache pre PHP. Toto zadarmošetrí zdroje.
  • Použite FastCGI (najlepšie je Nginx + PHP-fpm).
  • Funkcie v úlohách cron pomôžu vyhnúť sa úniku pamäte.
  • Ukladanie pomalých častí kódu do vyrovnávacej pamäte je často najjednoduchším riešením na zrýchlenie.
  • Spomeňte si na
  • Ako optimalizovať webovú stránku a zrýchliť jej výkon?
  • Akou rýchlosťou bude stránka fungovať a môže fungovať, v súlade s technológiami, na ktorých bude spustená?
  • Aké technológie by ste mali použiť pri nastavovaní servera alebo VPS?

Typický problém:
V určitom okamihu sa stránka začne otvárať a pracovať príliš pomaly. Stáva sa, že hostingová spoločnosť zablokuje stránku pre prekročenie záťaže alebo nadmerné využívanie zdrojov. Čo robiť v takejto situácii?

Je možné, že stránka je príliš navštevovaná alebo je nainštalovaný nejaký modul náročný na zdroje, prebieha útok alebo je stránka infikovaná vírusom. Tak či onak, všetky tieto prípady majú niečo do seba a to je problém všetkých stránok na všetkých hostingoch.

A ak hovoríme o serveroch pre PHP, tak takýmto problémom je spôsob, akým sa PHP kód spúšťa, rovnako ako iné významné nastavenia prostredia na serveri.
Bez ohľadu na to, či je vo vašom kóde problém alebo nie, či máte vysokú návštevnosť alebo nie, veľa závisí od nastavení servera. Aby všetko povedané neznelo ako prázdne slová, bol napísaný tento článok.

V tejto recenzii otestujem novo nainštalovanú stránku na jednom z najbežnejších nástrojov na správu obsahu Drupal 7.33.

Na test bol vybraný iba jeden komponent PHP hostingu. Budeme testovať webové servery Nginx A Apache2, moduly mod_php A php-fpm, verzie php php53 A php56, pozrime sa, ako ovplyvňujú optimalizátory apc A opcache na rýchlosti stránky.


Samozrejme, tieto parametre sú len časťou nastavení, od ktorých závisí rýchlosť stránky. Ale my schválne
Obmedzujeme sa na to, aby recenzia nebola nekonečná.

Vzhľadom na to:
  • Operačný systém Centos 6.7
  • Databázový server: MariaDB 10.21
  • Všetky relácie webovej stránky sú uložené v memcache, aby sa odstránil vplyv rýchlosti inštalácie relácie na rýchlosť webovej stránky.
  • Vo všetkých testoch slúži ako frontend webový server nginx 1.93. V prípade Apache2 funguje Nginx ako vyvažovač, ako aj pre statické doručovanie. V konfiguráciách bez použitia Apache2 je priamym webovým serverom Nginx
  • Konfigurácie Nginx a MariaDB obsahujú veľa optimalizácií zameraných na dosiahnutie maximálneho výkonu, ale pre všetkých účastníkov testu sú tieto nastavenia rovnaké, a preto ich vplyv treba ignorovať
  • Parametre opcache a apc sú prevzaté z odporúčaní Bitrix, pretože sú optimálne a univerzálne pre väčšinu stránok
Ako budeme testovať?

V lokálnej sieti je server zabbix a jeho úlohy každú minútu:

  • Otvorte hlavnú stránku testovanej lokality, počkajte na určitý obsah na stránke a uistite sa, že odpoveď zo servera je kód 200.
  • Ďalším krokom je autorizácia do oblasti správy stránky, to sa vykonáva odoslaním príslušnej požiadavky POST. Overenie textu a kódu odpovede na stránke s poskytnutým štandardom. Tento krok sa týka takmer všetkých subsystémov webového servera a jeho rýchlosť do značnej miery závisí od rýchlosti interakcie s databázou
  • Posledným krokom je opustiť oblasť správy lokality a skontrolovať kód odpovede a text na výstupnej stránke
  • Na základe výsledkov každého kroku zabbix dôsledne zmeria a zaznamená rýchlosť vykresľovania php kódu do html, ktorý je zrozumiteľný pre prehliadač, a ukáže nám grafy získaných výsledkov
  • Pre každý subjekt sa zaznamenajú hodnoty za jednu hodinu a výsledkom budú priemerné hodnoty za túto hodinu.
  • Testovanie bude prebiehať v rámci lokálnej siete, takže rýchlosť internetového pripojenia neovplyvní výsledok.
  • Pre uľahčenie vnímania zobrazujem všetky výsledky vo vzostupnom poradí. Tie. úplne prvý výsledok je najpomalší. Všetkým konfiguráciám bolo priradené podmienené číslo, čo vám umožní lepšie sa orientovať vo výsledkoch
  • Horné grafy zobrazujú rýchlosť generovania kódu, čím vyššia hodnota, tým lepšie. Nižšie grafy predstavujú čas odozvy servera a čím nižšia hodnota, tým lepšie
  • Testované stránky si žijú vlastným životom, vykonávajú pravidelné operácie s databázami a vykonávajú naplánované úlohy, preto krivka na grafoch môže mať vzostupy a pády

Testovanie:

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

Z hľadiska architektúry ide o jednu z najpokročilejších možností. Z hľadiska výkonu je to najväčšie sklamanie.

Výkon ponecháva veľa na želanie, ale táto možnosť znesie záťaž oveľa lepšie ako možnosť č. 2 s Apache2. Táto možnosť tiež využije RAM oveľa efektívnejšie.

2. Apache2 + mod_php53 bez optimalizátora apc

Najtypickejšia možnosť pre hosting. Túto možnosť využíva 90 % populárnych poskytovateľov hostingu. Hoci php53 vývojári dlhodobo nepodporujú, na internete je množstvo stránok, ktoré stále fungujú na tejto verzii.

Táto možnosť je nielen veľmi pomalá, ale tiež rýchlo spadne pri nízkej záťaži kvôli nedostatku pracovných procesov Apache2 alebo kvôli nedostatku pamäte RAM na serveri.

3. Vyvažovanie a statika cez Nginx, dynamická časť Apache2 + mod_php56 bez optimalizátora opcache

Táto možnosť bola vytvorená ako riešenie pre moderné webové stránky. Ponúkajú ho hostingové spoločnosti, ktoré sa snažia poskytovať najnovšiu verziu PHP. Podľa všeobecného presvedčenia by táto verzia PHP mala byť rýchlejšia a bezpečnejšia ako predchádzajúce.

Bohužiaľ, nie všetky stránky dokážu s touto verziou plne fungovať. Takmer každá nová verzia PHP prestáva podporovať niektoré zastarané a „nebezpečné“ funkcie, čím porušuje funkčnosť „starého“ kódu.
Samotné PHP56 bez optimalizátora je dosť pomalé a mod_php má tendenciu padať a zaberať všetku pamäť na serveri pri zaťažení.

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

Celkom pokročilá konfigurácia pre tých, ktorí nechcú mať problémy kvôli chybám s optimalizátorom kódu. V tomto prípade sa použije „kompatibilná“ verzia PHP interpreta a z balíka sa odstráni Apache2 náročný na zdroje.

5. Vyvažovanie a statika cez Nginx, dynamická časť Apache2 + mod_php53 + apc

Ďalšia bežná variácia. Mnoho hostiteľských stránok ho používa a buď ho používa predvolene, alebo dáva možnosť povoliť optimalizátor na svojich ovládacích paneloch.
Zvyčajne je Apache2 ponechaný na ovládanie pravidiel .htaccess, ako je preklad odkazov a CNC.

Získame 3,5-násobné zvýšenie rýchlosti v porovnaní s možnosťou bez použitia optimalizátora.
Samotný Apache (pomocou vlastného modulu mod_php) využíva na prevádzku oveľa viac zdrojov ako možnosť php-fpm. Apache2 má tendenciu padnúť, ak jeden z jeho modulov zlyhá alebo zaplní RAM celého servera.

6. Nginx + php-fpm53 + apc

Vynikajúca možnosť pre stránky na starších motoroch, ktoré nevyžadujú zložitý .htaccess

Presne túto možnosť využívam, keď potrebujem upgradovať zastaranú webovú stránku, dostať ju na uspokojivú rýchlosť a spoľahlivú prevádzku pri vysokej záťaži.

7. Vyvažovanie a statika cez Nginx, dynamická časť Apache2 + php-fpm53 + apc

Možnosť pre staršie stránky s komplexným .htaccess. Napríklad staré inštalácie Bitrix.

To je ideálne pre zastarané stránky. Táto konfigurácia je odolná voči vysokému zaťaženiu, kompatibilná a pomerne produktívna.
Skvelé, keď potrebujete pravidlá .htaccess a ďalšie moduly Apache2.
Nevýhodou je, že verzia PHP je zastaraná a neaktualizovaná, ale ak nie je na výber, je to najlepšia možnosť. Skvelé pre staré verzie Bitrix, Joomla a ďalšie bežné CMS, nie najnovšie verzie.

8. Vyvažovanie a statika cez Nginx, dynamická časť Apache2 + mod_php56 + opcache

Docela produktívna, ale na zdroje náročná konfigurácia so všetkými nedostatkami mod_php.

Pomerne rýchlo, ale pri zaťažení servera môže mať nedostatok pamäte a rýchlosť výrazne klesne.

9. Nginx + php-fpm56 + opcache

Najproduktívnejšia možnosť.

Toto je najlepšia možnosť pre všetky moderné stránky. Dobre drží záťaž a vykazuje najlepšie výsledky z hľadiska výkonu. Presne túto možnosť používam, keď je úlohou optimalizovať výkon stránky a zvýšiť jej rýchlosť.
Jedinou nevýhodou je, že nebudeme môcť používať .htaccess a všetky pravidlá mod_rewrite je potrebné prepísať na syntax Nginx.
Moduly Apache2 tiež nebudú fungovať. Ak sa použijú, táto možnosť nebude fungovať.

10. Vyvažovanie a statika cez Nginx, dynamická časť Apache2 + php-fpm56+ opcache

Najlepšia možnosť pre stránky, kde je potrebný .htaccess. Ideálne pre najnovšie verzie Bitrix.

Dobre drží záťaž vďaka php-fpm. Túto možnosť aktívne využívam pre väčšinu stránok.

Domovská stránka testovacieho webu
Číslo konfigurácie Architektúra Priemerná odozva 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
Autorizácia v administračnom paneli testovacej lokality
Číslo konfigurácie Architektúra Priemerná rýchlosť sťahovania kb. Priemerná odozva ms.
1 Nginx + php-fpm56 bez optimalizátora opcache 67,51 239,01
2 Apache2 + mod_php53 bez optimalizátora apc 64,61 257,51
3 Apache2 + mod_php56 bez optimalizátora opcache 66,75 242,42
4 Nginx + php-fpm53 bez optimalizátora 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ásenie z administračného panela testovacej lokality
Číslo konfigurácie Architektúra Priemerná rýchlosť sťahovania kb. Priemerná odozva ms.
1 Nginx + php-fpm56 bez optimalizátora opcache 41,01 184,49
2 Apache2 + mod_php53 bez optimalizátora apc 42,42 188,97
3 Apache2 + mod_php56 bez optimalizátora opcache 42,06 188,37
4 Nginx + php-fpm53 bez optimalizátora 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

Ako zhrnutie:

  • V reálnom živote môžu byť všetky možnosti s Apache2 pomalšie, pretože v mojich testoch som zámerne preniesol statický výstup do Nginx. Toto bolo urobené s cieľom eliminovať vplyv rýchlosti statického výstupu na výsledky merania rýchlosti PHP interpreta. Jednou z najslabších stránok Apache2 a zároveň silnou stránkou Nginxu je rýchlosť statického výstupu. Je to viditeľné najmä pri vysokom zaťažení. Okrem toho je Nginx menej náchylný na útok „pomalého pripojenia“.
  • mod_php veľmi rýchlo zaberá všetku dostupnú pamäť servera a pri zaťažení stráca výkon
  • php-fpm využíva pamäť oveľa efektívnejšie, bezpečnejšie a flexibilnejšie v nastaveniach. V niektorých prípadoch je rýchlejší a bez vysokého zaťaženia.
  • Test má úzku špecifickosť, tu sme videli zvláštnosti Drupal enginu, iné sa môžu správať inak, ale všeobecný trend bude rovnaký.

A čo je najdôležitejšie, rýchlosť vášho webu závisí od konfigurácie vášho servera alebo hostingu. Výberom správnej architektúry môžete dosiahnuť päťnásobné zvýšenie rýchlosti webu.

Ak máte nejaké otázky, ťažkosti alebo potrebujete poradiť:
Moje kontakty v

Od autora: Každý sebarešpektujúci vývojár sa obáva o „osud“ svojho kódu. Snaží sa, aby bola aplikácia čo najpohodlnejšia, rýchlejšia a zvýšila jej odolnosť voči chybám. Ale PHP optimalizácia vám nie vždy umožní dosiahnuť tieto výšky.

Neliečte si ruku, ak máte chromú nohu!

Prepáčte za írsky ľudový aforizmus! Ale dokonale odráža podstatu problému. Optimalizácia kódu vám najčastejšie neumožní zlepšiť výkon vytvoreného skriptu alebo prostriedku. A v prípade , sa všetko extrémne skomplikuje kvôli veľkému množstvu faktorov, ktoré vy (ako vývojár) jednoducho nemôžete ovplyvniť.

Pokiaľ ide o javy, ktoré nemôžeme ovplyvniť, mám na mysli rýchlosť internetového pripojenia, zaťaženie servera, nastavenia operačného systému na klientskom počítači a výkon hardvéru počítača používateľa. Všetky tieto zložky neovplyvníte. A nakoniec sa ukáže, že optimalizácia kódu PHP neprinesie úplný výsledok.

Čo zostáva pod kontrolou webového vývojára:

Nastavenia servera sú obmedzené. Nastavenie parametrov cez konfiguračný súbor Apache httpd.conf umožňuje nastaviť počet podriadených procesov, časový limit pripojenia soketu, veľkosť výstupnej vyrovnávacej pamäte pre pripojenia TCP/IP, čas nečinnosti a iné.

Nastavenia jazykového jadra - cez parametre uvedené v súbore php.ini. Umožňuje nastaviť hodnoty vyrovnávacej pamäte, zmeniť maximálny čas vykonávania skriptu, spracovanie chýb, správu protokolov a ďalšie nastavenia.

Používanie optimalizácie obrázkov PHP – o tom neskôr. Optimalizácia programového kódu - umožňuje „ušetriť“ zdroje a zvýšiť výkon.

Napríklad musíte vedieť, že ozvena je rýchlejšia ako tlač. Po ladení je lepšie vypnúť chybové hlásenia, aby ste ušetrili zdroje. Namiesto zreťazenia reťazcov použite echo. Objekty a metódy triedy () zaberajú veľa pamäte.

Práca s obrázkami

Nie som fanúšikom spracovania obrazu na strane servera. To tiež vedie k plytvaniu vzácnymi zdrojmi, ktorých je hosting vždy nedostatok. Ukazuje sa, že šetrením na jednej veci míňame ďalšie „rezervy“.

Optimálnejšou možnosťou je nahrať obrázky do služby tretej strany, odkiaľ sa načítajú v optimalizovanej podobe do prehliadača používateľa na danej adrese. Takýchto služieb je na internete veľa. Chcem vymenovať len niektoré z nich: kraken.io, TinyPNG

Ako vidíte, dôležitá je aj znalosť optimalizácie pre vyhľadávače v PHP pre profesionálnych vývojárov.

Okrem toho má vlastné vstavané nástroje na „zosvetlenie“ obrázkov. Napríklad funkcia imagecopyresampled(). Znižuje váhu obsahu prevzorkovaním a zmenou veľkosti obrázka. Príklad použitia:

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

$subor = "ukážka.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) ;

Čo ešte môžeš urobiť?

Nezabudnite tiež použiť optimalizáciu na strane klienta pomocou PHP. Server môže do určitej miery ovplyvniť klientsky prehliadač prostredníctvom Cache-Control, ako aj atribúty tejto hlavičky: post-check, max-age a iné.

Okrem toho hlavičky Last-Modified a ETag umožňujú spravovať stav vyrovnávacej pamäte na klientskom počítači. Nastavujú jedinečné ID na úpravu každého súboru. Vďaka tomu server znova neposiela zdroje, ale odpovedá iba so stavom 304.

V článku sme nenastolili otázku optimalizácie pomocou PHP FPM. Ale zvážiť to bude vyžadovať samostatný článok. To je na dnes všetko. Dobudúcna!

Témou tohto článku je fakt, že použitie FastCGI v PHP nezrýchli čas načítania PHP kódu v porovnaní napríklad s mod_php.

Väčšina tradičných webových programovacích jazykov (Perl, Ruby, Python atď.) podporuje písanie skriptov, ktoré pracujú v takzvanom „režime FastCGI“. Navyše, napríklad Ruby on Rails sa v režime CGI nedá použiť vôbec, pretože trávi desiatky sekúnd spájaním všetkých svojich početných knižníc.

Nižšie budem hovoriť o metóde, ktorá v niektorých prípadoch umožňuje zrýchliť načítanie objemného PHP kódu viac ako 20-krát bez vedľajších účinkov alebo výrazných nepríjemností. Najprv si však povedzme o základoch...

Čo je FastCGI?

Najprv si povedzme o tom, čo sa nazýva „klasické“ FastCGI, ktoré sa používa v jazykoch C, Perl, Ruby atď. V PHP má FastCGI svoje vlastné charakteristiky, pozrieme sa na ne o niečo neskôr. Teraz hovoríme o non-PHP.

FastCGI funguje takto: skript sa načíta do pamäte, spustí nejaký ťažký inicializačný kód (napríklad vrátane veľkých knižníc) a potom vstúpi do slučky na spracovanie prichádzajúcich požiadaviek HTTP. Rovnaký skriptový proces spracováva niekoľko rôznych požiadaviek jednu po druhej, čo sa líši od práce v režime CGI, keď je pre každú požiadavku vytvorený samostatný proces, ktorý po dokončení spracovania „umiera“. Zvyčajne po spracovaní N požiadaviek sa skript FastCGI ukončí, takže ho server znova reštartuje v „čistom karanténe“.

Pre urýchlenie spracovania sa samozrejme nespustí jeden proces skriptu, ale hneď niekoľko, aby každá ďalšia požiadavka nečakala na spracovanie predchádzajúcej. V konfigurácii servera je možné nastaviť počet súčasne spustených procesov aj počet sekvenčných požiadaviek na proces.

Staré skripty napísané s ohľadom na CGI je potrebné upraviť, aby mohli pracovať v prostredí FastCGI (platí pre použitie FastCGI v C, Perl atď.; v PHP nie je potrebná žiadna úprava, ale má to svoje nevýhody, pozri nižšie) . Skutočne, predtým sa scenár začínal zakaždým „od nuly“, ale teraz sa musí vysporiadať s „odpadom“, ktorý zostal z predchádzajúcej požiadavky. Ak predtým vyzeral CGI skript v Perle

použiteSomeHeavyLibrary; print "Ahoj, svet!\n";

potom po úprave pre FastCGI to vyzerá ako niečo podobné

použiteSomeHeavyLibrary; while ($request = get_fastcgi_request()) (tlač "Ahoj, svet!\n"; )

Výsledkom je úspora rýchlosti odozvy: koniec koncov, vždy, keď príde požiadavka, skript nemusí spustiť „ťažký“ inicializačný kód knižnice (niekedy to trvá desiatky sekúnd).

FastCGI má významnú nevýhodu: nová požiadavka sa začína spracovávať nie v „čistom“ prostredí, ale v prostredí, ktoré zostalo „z poslednej doby“. Ak má skript úniky pamäte, postupne sa hromadia, až kým nepadne. To isté platí pre zdroje, ktoré zabudli uvoľniť (otvorené súbory, pripojenia k databáze atď.). Existuje ešte jedna nevýhoda: ak sa kód skriptu zmenil, musíte o tom nejakým spôsobom informovať server FastCGI, aby „zabil“ všetky svoje procesy a začal znova.

V skutočnosti technika „iniciovať raz, spracovať veľa požiadaviek“ funguje nielen vo FastCGI. Každý server napísaný v rovnakom jazyku ako skript spustený pod ním ho implicitne používa. Napríklad server Mongrel je napísaný celý v Ruby práve preto, aby sa pod ním rýchlo spúšťal Ruby On Rails. Server Apache Tomcat, napísaný v jazyku Java, rýchlo spúšťa servlety Java, pretože... nevyžaduje ich opätovnú inicializáciu. Technológia mod_perl je tiež založená na skutočnosti, že kód Perl sa medzi požiadavkami neuvoľňuje, ale zostáva v pamäti. Všetky tieto servery majú samozrejme rovnaké problémy s nepredvídateľnosťou, únikmi pamäte a ťažkosťami pri reštartovaní ako aplikácia FastCGI.

Prečo FastCGI nezrýchľuje PHP

Určite ste už počuli, že PHP je možné spustiť aj v režime FastCGI a že to robí veľa projektov s vysokou záťažou (Mamba, niektoré projekty Mail.Ru atď.). To údajne dáva "výrazné zvýšenie" výkonu, pretože (podľa povestí) FastCGI šetrí čas na inicializáciu skriptov a zahrnutie knižnice.

Neverte tomu! V skutočnosti je podpora FastCGI PHP čisto nominálna. Presnejšie, neposkytuje výhody v zmysle, v akom sa používa na skrátenie času inicializácie skriptu. Samozrejme, môžete spustiť PHP FastCGI server a dokonca s ním priamo pracovať nginx alebo lighttpd, ale zrýchlenie, ktoré získate načítaním kódu, bude nulové. Ťažké PHP knižnice (napríklad Zend Framework) sa v režimoch mod_php alebo CGI načítali dlho a v režime FastCGI sa budú načítavať ešte dlho.

V skutočnosti to nie je prekvapujúce: koniec koncov, ak chcete spustiť akýkoľvek PHP skript v režime FastCGI, nemusíte ho upravovať. Ani jeden riadok zmeneného kódu! Keď som sa prvýkrát rozhodol experimentovať s FastCGI v PHP, strávil som niekoľko hodín hľadaním informácií na internete, ako presne upraviť PHP kód, aby sa optimálne spúšťal v režime FastCGI. Prešiel som celú PHP dokumentáciu a niekoľko desiatok PHP vývojárskych fór, dokonca som sa pozrel na zdrojový kód PHP, ale stále som nenašiel jediné odporúčanie. Po predchádzajúcej skúsenosti s FastCGI v jazyku Perl a C som bol neuveriteľne prekvapený. Všetko však zapadlo, keď sa ukázalo, že nie je potrebné meniť kód a hoci sa v rámci jedného FastCGI procesu spracováva niekoľko spojení, PHP interpret sa inicializuje zakaždým nanovo (na rozdiel od „klasického“ FastCGI). Navyše sa zdá, že väčšina PHP vývojárov, ktorí s radosťou používajú FastCGI+PHP, si ani neuvedomuje, že by to malo fungovať inak...

eAccelerator: Zrýchlenie opätovného načítania kódu PHP

Zakaždým, keď PHP skript dostane kontrolu, PHP skompiluje (presnejšie preloží) kód skriptu do internej reprezentácie (bytecode). Ak je súbor malý, preklad prebieha veľmi rýchlo (Zend Engine v PHP je jedným z lídrov v rýchlosti prekladu), ak však zahrnuté knižnice „vážia“ niekoľko megabajtov, preklad sa oneskorí.

Existuje množstvo nástrojov, ktoré ukladajú preloženú internú reprezentáciu kódu PHP do vyrovnávacej pamäte v zdieľanej pamäti. Keď sa teda súbor PHP znova povolí, už sa neprekladá a bajtový kód sa prevezme z vyrovnávacej pamäte v pamäti. To samozrejme výrazne urýchľuje prácu.

Jedným z takýchto nástrojov je eAccelerator. Inštaluje sa ako rozšírenie PHP (pripojené v php.ini) a vyžaduje veľmi minimálnu konfiguráciu. Režim bytecode caching odporúčam povoliť výhradne v RAM a vypnúť kompresiu (nastaviť parametre eaccelerator.shm_only=1 a eaccelerator.compress=0). Nainštalujte a nakonfigurujte aj ovládací panel control.php, ktorý je súčasťou distribúcie eAccelerator, aby ste mohli sledovať stav vyrovnávacej pamäte v reálnom čase. Bez ovládacieho panela bude pre vás veľmi ťažké diagnostikovať, ak eAccelerator z nejakého dôvodu nefunguje.

Výhodou eAcceleratora je, že funguje veľmi stabilne a rýchlo aj na veľkých objemoch PHP kódu. S týmto nástrojom som nikdy nemal žiadne problémy (napríklad na rozdiel od Zend Accelerator).

“Môj skript spolu s knižnicami zaberá 5 MB, čo mám robiť?...”

Zdá sa vám 5 MB kódu na PHP priveľa? Nič také. Vyskúšajte systémy ako Zend Framework a Propel, aby ste videli inak. Celý Zend Framework zaberá približne 5 MB. Triedy generované Propelom sú tiež pomerne veľké a môžu zaberať niekoľko ďalších megabajtov.

Mnoho ľudí sa na tomto mieste pousmeje a povie, že nie je potrebné používať Zend Framework a Propel, pretože... sú pomalé. Ale realita je taká, že nie sú vôbec pomalé... Metóda, ktorá štandardne používa PHP na načítanie kódu, má slabý výkon. Našťastie nie je ťažké situáciu napraviť.

Aby som nebol neopodstatnený, uvediem výsledky malého testu, ktorý som konkrétne vykonal v „čistom“ prostredí, ktoré nie je viazané na žiadny konkrétny projekt. Testovala sa rýchlosť pripojenia všetkých súborov Zend Framework (s výnimkou Zend_Search_Lucene). Všetky volania require_once boli predtým z kódu odstránené a závislosti boli načítané iba prostredníctvom mechanizmu automatického načítania.

Celkovo bolo teda pripojených 790 PHP súborov s celkovým objemom 4,9 MB. Pomerne veľa, však? Spojenie prebiehalo asi takto:

function __autoload($className) ( $fname = str_replace("_", "/", $className) . ".php"; $result = require_once($fname); return $result; ) // Spojte triedy jeden po druhom jeden v poradí ich 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 ďalej pre všetkých 790 súborov

Pretože sa používa automatické načítanie, volanie class_exists() núti PHP zahrnúť príslušný súbor triedy. (Toto je najjednoduchší spôsob, ako „vytiahnuť“ funkciu autoload.) Poradie pripojenia som zvolil tak, že každá nasledujúca trieda už mala v čase spustenia načítané všetky svoje závislé triedy. (Toto poradie sa dá ľahko určiť jednoduchým vytlačením hodnoty $fname vo funkcii __autoload do prehliadača.)

Tu sú výsledky testov s eAcceleratorom a bez neho na mojom nie príliš výkonnom notebooku (Apache, mod_php):

  • Pripojenie všetkých súborov po jednom, eAccelerator vypnutý: 911 ms.
  • Pripojenie všetkých súborov jeden po druhom, eAccelerator povolený: 435 ms. 15 M vyrovnávacej pamäte je obsadených pre bajtový kód.

Ako vidíte, eAccelerator poskytuje približne 2x zrýchlenie na 790 súboroch s celkovým objemom 4,9 MB. Trochu slabé. Navyše 435 ms je zjavne príliš veľa na skript, ktorý nerobí nič iné, len obsahuje knižnice.

Teraz pridajme nejaké steroidy

Hovorí sa, že PHP načítava jeden veľký súbor oveľa rýchlejšie ako desať malých s rovnakou celkovou veľkosťou. Rozhodol som sa otestovať toto tvrdenie spojením celého Zend Frameworku do jedného súboru s veľkosťou 4,9 MB a jeho spojením pomocou jediného volania require_once. Pozrime sa, čo sa stalo.

  • Povolenie jedného veľkého zlúčeného súboru, eAccelerator vypnutý: 458 ms.
  • Povolenie jedného veľkého zlúčeného súboru, eAccelerator zapnuté: 42 ms. Je obsadených 31 MB vyrovnávacej pamäte bajtového kódu.

Prvý riadok hovorí, že jeden veľký súbor s veľkosťou 4,9 MB sa v skutočnosti načíta rýchlejšie ako 790 malých: 458 ms oproti 911 ms (pozri vyššie). 2x úspora.

Ale druhý riadok ma prinútil skákať na stoličke od prekvapenia a niekoľkokrát skontrolovať výsledok. Dúfam, že sa vám stane to isté. Skutočne, 42 ms je 11-krát rýchlejšie ako s vypnutým eAcceleratorom! Ukazuje sa, že eAccelerator miluje malé súbory ešte menej (mimochodom, dokonca aj v režime eaccelerator.check_mtime=0): 11-násobná úspora.

V skutočnosti sme teda získali 22-krát rýchlejšie časy načítania, ako sa sľubuje v názve. Predtým celý Zend Framework rozdelený na súbory trvalo pripojenie 911 ms a pomocou eAccelerator a skombinovaním všetkých súborov do jedného - 42 ms. A toto, uvedomte si, nie je na skutočnom serveri, ale len na obyčajnom notebooku.

Záver: 22-krát rýchlejšie

Poďme si to zhrnúť.

  • Zlúčenie všetkých súborov do jedného veľkého súboru plus aktivácia eAccelerator pre tento veľký súbor poskytuje 22x zrýchlenie s veľkosťou kódu 4,9 MB a počtom 790 súborov.
  • Pre malý počet veľkých súborov môže eAccelerator poskytnúť 10x zrýchlenie. Ak existuje veľa súborov a celkový objem je veľký, zrýchlenie je približne 2-násobné.
  • Spotreba vyrovnávacej pamäte závisí od počtu súborov oddielov: pre pevnú veľkosť platí, že čím viac súborov je, tým menšia spotreba.

Vďaka tomu všetkému eAccelerator nemá hlavné problémy „skutočného“ servera FastCGI. Skripty neobsahujú úniky pamäte a bežia v zaručene „čistom“ prostredí. Tiež nemusíte monitorovať zmeny kódu a reštartovať server zakaždým, keď sa vykonajú úpravy vo viac či menej hlbokom kóde systému.

Všimnite si tiež, že sme zahrnuli celý rámec Zend. V skutočných skriptoch bude množstvo kódu oveľa menšie, pretože Na prevádzku je zvyčajne potrebná len malá časť ZF. Ale aj keď knižnice zaberajú 4,9 MB, dostaneme čas načítania 42 ms - celkom prijateľné pre PHP skript. Koniec koncov, v rušných projektoch môžu PHP skripty fungovať niekoľko stoviek milisekúnd (Facebook, My Circle atď.).

Samozrejme, ak plánujete spustiť FastCGI v PHP nie z dôvodov výkonu, ale jednoducho preto, aby ste sa vyhli viazaniu na Apache a obmedzili sa na kombináciu „nginx+PHP“ alebo „lighttpd+PHP“, nič tomu nebráni. Navyše, použitím eAccelerator pre FastCGI+PHP a zlúčením mnohých kódových súborov do jedného veľkého, získate rovnaké zrýchlenie, aké som opísal vyššie. Nelichotte si však nádejami, že zrýchlenie poskytlo FastCGI: nie je to tak. Pomocou mod_php+eAccelerator by ste dosiahli takmer rovnaký výsledok ako FastCGI+eAccelerator.

Manuálne zlučovanie všetkých súborov knižnice do jedného je únavná úloha. Je lepšie napísať pomôcku, ktorá automaticky analyzuje zoznam súborov PHP zahrnutých v skripte a pri ďalšom spustení tieto súbory skombinovať a zapísať do dočasného adresára (ak sa tak ešte nestalo) a potom ich pripojte pomocou require_once. Dnes nechávam napísanie takejto pomôcky (uveďte alebo vezmite podrobnosti) na svedomie čitateľa.

Odporúčam tiež, aby ste opustili explicitné zahrnutie súborov pomocou require_once a prešli na automatické načítanie. Len sa na to nepokúšajte použiť Zend_Loader: je veľmi pomalý (podľa mojich meraní bude pripojenie stovky súborov trvať asi 50 ms navyše). Je lepšie napísať si vlastnú jednoduchú funkciu automatického načítania, ktorá rýchlo urobí všetku prácu. Automatické načítanie vám umožní bezpečne skombinovať viacero súborov knižnice do jedného bez toho, aby ste sa museli obávať, že budete musieť riešiť manuálne require_onces.

Nakoniec použite funkciu set_include_path(), aby kód zahrnutia knižnice vyzeral takto:

require_once "Some/Library.php";

vyžadovať_raz LIB_DIR . "/Some/Library.php";

Konštanty, ktoré explicitne definujú cestu do adresára knižnice sú veľké zlo a komplikujú program. Nepriamo odporujú aj štandardom kódovania Zend Framework a PEAR, ktoré tiež odporúčam dodržiavať vždy, keď je to možné.

Takže, ak chcete používať „ťažké“ knižnice v PHP skriptoch, veľa šťastia! PHP je skriptovací jazyk, ktorý vám to skutočne umožňuje bez ohľadu na nepríjemnosti FastCGI a problémy „zabudovaných“ serverov.