Optymalizacje PHP - fakty i mity, cz. 1


O optymalizowaniu skryptów napisanych w PHP bardzo wiele było już napisane. Często sugerowane metody optymalizacji nie są wytłumaczone, ani nie pokazuje się jaki przyrost wydajności uzyskamy przez ich wykorzystywanie. Część optymalizacji zmusza nas do całkowitego przebudowania programów, czego wolelibyśmy uniknąć.

Postaram się więc w tym wpisie przybliżyć 5 metod optymalizacji skryptów, nie ingerujących zbytnio w strukturę aplikacji. Omówię też które naprawdę dają efekt, a które chociaż dają - dają efekt niezauważalny.

1. Korzystanie z funkcji wbudowanych

Może tak od prostszych zagadnień zaczynając. Spróbujmy wypisać zawartość jakiegoś pliku. Wielu od razu napiszę do tego funkcję (a jak, nie będziemy tego robić za każdym razem!)

function print_file($src){
	print fread(fopen($src, 'r'),filesize($src));
}


Oj, źle. Co po niektórzy zaproponują trochę lepsze rozwiązanie.

function print_file($src){
	print file_get_contents($src);
}


Nadal niedobrze. Oczywiście powinniśmy skorzystać z gotowej funkcji readfile($src)! Różnica polega na tym że funkcja readfile, jak czytamy w specyfikacji jest w każdej implementacji parsera zoptymalizowana pod katem systemu operacyjnego, na którym pracuje serwer. Umożliwia to minimalny wzrost wydajności.

Wzrost wydajności: Średni

Czas wykonywania skryptu spadł z 30,748950005 sekund do 1,005427122 sekund czyli o 0,000297435 sekundy na pojedyncze wypisanie zwartości pliku.

Metoda pomiaru: 100 000. zapętlenie skryptu wypisującego na standardowe wyjście danego pliku o wielkości 8B.

2. Pojedyncze cudzysłowy zamiast podwójnych

Otoczenie stringu pojedynczy cudzysłowem powinno przyspieszyć parsowanie skryptu. Czy to prawda? Owszem. Dzieje się tak dla tego, że w stringach zdefiniowanych przy pomocy pojedynczych cudzysłowów parser nie szuka zmiennych. Jednak jeśli wziąć pod uwagę przyspieszenie jakie dzięki temu zyskujemy... strata czasu.

Wzrost wydajności: Mały.

Czas wykonywania skryptu spadł z 120,291386127 sekund do 107,389734983 sekund czyli o 0,000129017 sekundy dla pojedynczego ciągu.

Metoda pomiaru: 100 000. zapętlenie skryptu wypisującego na standardowe wyjście ciągu 1024 znaków.

3. Maksymalne uproszczanie obliczeń

W programach pisanych w językach kompilowanych przez inteligentne kompilatory (np c++) możemy zignorować kwestię optymalizacji niektórych działań matematycznych. Możemy na przykład zapisać:
x = 128 / 3 * 5;

Tutaj sprawa ma się trochę inaczej - również MOŻEMY pozostać przy takiej notacji, ale będzie ona wymagała każdorazowo obliczenia przez parser wartości (która z resztą wynosi 213,(3)).

Wzrost wydajności: Niezauważalny.

Czas wykonywania skryptu spadł z 0,001573086 sekundy do 0,001053095 sekundy, czyli o 0,000000001 sekundy na operację.

Metoda pomiaru: 1000 000 zapętlenie przypisania wyrażenia oraz liczby równej wynikowi wyrażenia.


4. Print czy echo?

Niby równoznaczne funkcje, jednakże dają znaczną różnicę wydajności. To co teraz napiszę nie spodoba się programistom, przyzwyczajonym do składni języków c-podobnych - na korzyść "echo".

Wzrost wydajności: Bardzo mały.

Czas wykonywania skryptu spadł z 0,10938096 sekundy do 0,012012959 sekundy, czyli o 0,000000974 sekundy na próbę.

Metoda pomiaru: 100 000. zapętlenie skryptu wypisującego znak funkcjami "echo" i "print".


5. Conditions czyli przypadki

A jakby tak nie używać instrukcji warunkowych? Czy można pozbyć się z programu tych podstawowych, ale jakże w niektórych dziedzinach programowania (np. pisanie shaderów) wolnych instrukcji? Czasem można je zastąpić instrukcjami o podobnych, ale ograniczonych możliwościach (celowo pomijam wyższość shwich'a nad if ... else → temat wydaje mi się wszystkim znany).


Dla przykładu spróbujmy skrócić zapis:

if($z == true) {
	$x = 'Masz rację :)';
}
else {
	$x = 'Mylisz się :(';
}


Jak to będzie wyglądało?

$x = ($z) ? 'Masz rację :)' : 'Mylisz się :(';


Nieprawda, że krócej? No to teraz zobaczmy jak z prędkością:

Wzrost wydajności: Ekstremalnie mały.

Czas wykonywania skryptu spadł z 0,242800951 sekundy do 0,184250832 sekundy czyli o 0,000000059 sekundy na operację.

Metoda pomiaru: 1000 000. zapętlenie skryptu wykonującego przypisanie przy pomocy instrukcji warunkowej i warunków potrójnych.



Część dalsza nastąpi. Chyba że w końcu napiszę o ładowaniu obiektów 3d .obj do OpenGL ;)

Dodał(a): m-krassowski, 09.12.12

Komentarze:

Brak komentarzy

Jesteś niezalogowany, zaloguj się, aby móc dodawać komentarze.