Google – Hai să facem web-ul mai rapid în PHP
9 Google e declarată în mod indirect una dintre cele mai importante companii internaţionale care încurajează dezvoltarea unor aplicaţii cât mai optimizate şi mai rapide. Acest fapt s-a văzut de-a lungul timpului prin uneltele realizate de ei, prin modificările ce le-au suferit algoritmii ce stau la baza motorului de căutare dar şi prin articole în care sunt prezentaţi diferiţi paşi pentru a scrie cod mai optimizat. Eric Higgins, unul dintre webmasterii de la Google a scris un articol ce cuprinde o serie de sfaturi utile pentru a optimiza experienţele utilizatorilor. Acesta s-a axat exclusiv pe PHP, unul dintre cele mai populare limbaje de programare în randul dezvoltatorilor web.
Profilează codul
De cele mai multe ori, ajungem să optimizăm aplicaţiile web abia după ce ne confruntăm cu probleme de stabilitate. Problema e că atunci suntem nevoiţi să optimizăm, dar nu prea ştim ce. Una dintre cele mai bune abordări în astfel de situaţii este profilarea aplicaţiilor. Vă recomand in xDebug.
Actualizează versiunea PHP
Îmbunătăţirile şi optimizările apar o dată cu fiecare nouă versiune PHP. E o abordare elegantă şi eficientă să vă aflaţi la zi cu versiunea PHP.
Migrarea de la PHP 4 la PHP 5.0.x
Migrarea de la PHP 5.0.x la PHP 5.1.x
Migrarea de la PHP 5.1.x la PHP 5.2.x
Folosiţi cache
Google recomandă să folosim module de caching precum MemCached sau sisteme de template-uri care suportă cache precum Smarty.
Jucaţi-vă cu bufferele pentru output
PHP foloseşte nişte buffere ce stochează în memorie tot ce va urma să fie afişat. Acestea nu trimit nimic browserului până în momentul în care acesta nu se încarcă. Din fericire, PHP suportă şi câteva îmbunătăţiri în acest sens (funcţiile de flush). Mai multe detalii aici.
Evitaţi folosirea unor funcţii de set şi get evidente
Renunţaţi la folosirea unor funcţii naive de setare a unor variabile atunci când realizaţi clase, precum cele din exemplul de mai jos. Este indicat să accesaţi direct funcţiile pentru că vă poate aduce o îmbunătăţire de 100% a vitezei pe acele acţiuni.
class dog { public $name = ''; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } }
Aşa nu!
$rover = new dog(); $rover->setName('rover'); echo $rover->getName();
Aşa da
$rover = new dog(); $rover->name = 'rover'; echo $rover->name;
Nu copiaţi variabile pentru nici un motiv
Evitaţi folosirea unor variabile suplimentare atunci când nu este cazul. Asta va duce la dublarea cantităţii de memorie folosită. Spre exemplu, dacă utilizatorul trimite un mesaj de 512KB prin parametrul de mai jos, codul va duce la folosirea unui MB de memorie. Gândiţi-vă la cantităţile de informaţii care trebuie să le suporte o aplicaţie web.
Aşa nu!
$description = strip_tags($_POST['description']); echo $description;
Aşa da!
echo strip_tags($_POST['description']);
Evitaţi executarea unor interogări în cicluri
Una dintre cele mai mari greşeli de logică în accesarea unei baze de date (ce am întâlnit-o şi eu de nenumărate ori) este executarea unor interogări în interiorul unui ciclu, ceea ce duce la o încetinire drastică a scriptului datorită numeroaselor apelări ale bazei de date. Astfel :
foreach ($userList as $user) { $query = 'INSERT INTO users (first_name,last_name) VALUES("' . $user['first_name'] . '", "' . $user['last_name'] . '")'; mysql_query($query); }
Produce :
INSERT INTO users (first_name,last_name) VALUES("John", "Doe")
Dar :
$userData = array(); foreach ($userList as $user) { $userData[] = '("' . $user['first_name'] . '", "' . $user['last_name'] . '")'; } $query = 'INSERT INTO users (first_name,last_name) VALUES' . implode(',', $userData); mysql_query($query);
Produce :
INSERT INTO users (first_name,last_name) VALUES("John", "Doe"),("Jane", "Doe")...
Evitaţi folosirea unor funcţii pentru condiţiile de oprire ale unor cicluri
O altă abordare greşită este folosirea unor funcţii precum strlen, sizeof şamd. în stabilirea punctului de oprire a unui ciclu precum for sau while. Astfel, prima abordare de mai jos este greşită, în vreme ce a doua este cea corectă.
Aşa nu!
for($i = 0; $i<sizeof($arr); $i++) { echo $arr[$i]; }
Aşa da!
$n = sizeof($arr); for($i=0;$i<$n;$i++) { echo $arr[$i]; }
Ciclurile for sunt cu 38% mai rapide decât cele foreach
Un aspect pe care mi l-a sesizat Roland. A scris un articol detaliat despre această observaţie aici.
Există numeroase alte greşeli care duc la scăderea vitezei unui script PHP. Aştept alte păreri şi observaţii pentru a completa acest articol.
Daca acest articol contine o greseala, selecteaza cuvintele sau fraza gresita si tasteaza combinatia de taste Shift + Enter sau apasa click aici pentru a o raporta. Multumim!
Cred ca la linia a 2-a trebuie $i<$n .
Corect. Mersi de observatie. 🙂
Daca nu folosim functii de set si get in clase, nu se pierde principiul de incapsulare al programarii orientate pe obiect?
@kNigHt
Ba da. Ciudat e ca in majoritatea limbajelor pe care le-am folosit accessor si mutator methods imbunatatesc viteza. Nu stiam ca in php e invers.
Daca tot vorbim de performanta, ar mai fi de zis ca Nginx e mai rapid ca Apache si ca ar trebui sa folosim Nginx cu php-fpm si poate baze de date NoSql cand e cazul.
@Dinu
In ce limbaj de programare cele doua metode imbunatatesc viteza? Poate un apel de functie (metoda) fi mai rapid decat accesul direct la un atribut?
In opinia mea, un apel de astfel de metoda va fi intotdeauna (cu exceptia metodelor inline din C++) mai lent decat accesul direct.
@kNigHt
exemplul dat are o mica „hiba”. Pentru a permite a doua metoda de acces (cea directa) , atributul name a fost declarat public. In acest caz, este evident ca existenta unei metode get/set este inutila si prima varianta este gresita. Dar, dupa cum spuneai si tu, se pierde incapsularea.
Eu sincer nu stiu ce vrea sa spuna autorul prin „funcţii de set şi get evidente”. Daca se refera la existenta unei functii set/get pentru membrii publici atunci sunt foarte de acord ca este o greseala. Altfel, tot timpul o functie set sau get va fi „evidenta”, dar are un scop foarte bine definit in POO.
Google recomandă să folosim module de caching precum MemCached sau sisteme de template-uri care suportă cache precum Smarty.
Adica daca folosesc Smarty NU mai are rost sa folosesc MemCached sau cum ?ca eu nu inteleg..
Si pana la urma Smarty ajuta la scalabilitate sau nu?
@Razvan Smarty eu un framework. Nu are nicio treaba. Memcached e o treaba iar Smarty e o alta. 🙂
pai stiu ca nu au nici o legatura intre ele…dar ajuta la scalabilitate smarti-ul?