publikuj: Opublikuj w wykop.pl Opublikuj we flaker.pl Opublikuj na OSnews.pl Opublikuj w delicious wydrukuj
17 skomentuj »

TAGI: programowanie , php

2008-09-30 09:20  |  Piotr Ostalecki

Przyspieszamy skrypty PHP (kilka prostych wskazówek)

Przyspieszamy skrypty PHP (kilka prostych wskazówek)

Wykonanie przeciętnego skryptu napisanego w PHP trwa kilka milisekund i dla zwykłego użytkownika jest praktycznie niezauważalne. Jednak w wypadku popularnych witryn i dużych fragmentów kodu liczą się każda milisekunda i każdy kilobajt danych. Projektant aplikacji sieciowej nie może więc poprzestać jedynie na unikaniu w tworzonym kodzie najpoważniejszych błędów. Warto także już na początku swojej programistycznej edukacji zapoznać się z kilkoma praktycznymi wskazówkami, które pozwolą uczynić projektowane w przyszłości rozwiązania bardziej wydajnymi.


1. Zredukuj liczbę wywołań funkcji

Przyjrzyjmy się poniższemu fragmentowi kodu:

$array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
for($a = 0; $a < sizeof($array); $a++) {
// (…)
}

Funkcja sizeof() jest w tym wypadku wywoływana aż dwadzieścia jeden razy – całkowicie bez potrzeby. Wystarczyłoby, po jednokrotnym jej uruchomieniu, zapisać wielkość tablicy do zmiennej, a później po prostu wielokrotnie wykonać pętlę:

$array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
$size = sizeof($array);

for($a = 0; $a < $size; $a++) {
// (…)
}

Aby sprawdzić, czy podana wskazówka faktycznie pozwala zredukować czas realizacji działania skryptu, wykonaliśmy praktyczną próbę: najpierw uruchomiliśmy pierwszy skrypt, korzystając z tablicy z dziesięcioma tysiącami elementów, a następnie drugą jego wersję – przy użyciu tej samej tablicy. W rezultacie czas wykonywania zmniejszył się o ponad 50% (z 0,0278 do 0,0128 sekundy).


2. Oszczędzaj pamięć

Unikajmy tworzenia tysięcy zmiennych tylko po to, aby przechować w nich tekst, który później wyświetlimy, korzystając z instrukcji echo. Zamiast poniższego kodu:

$string = 'Ala ma kota';
echo $string;

napiszmy po prostu:

echo ‘Ala ma kota’;

Jeśli jednak musimy koniecznie przechować coś dużego w zmiennej, pamiętajmy, by ją później zlikwidować za pomocą polecenia unset($zmienna).


3. Co wybrać: str_replace() czy ereg_replace()? A może preg_replace()?

Gdy do wyszukiwania i zamiany fragmentów tekstu stosujemy wyrażenia regularne, musimy bez wątpienia wykorzystać jedną z funkcji: ereg_replace() lub preg_replace(). Kiedy jednak chcemy po prostu wyszukać w tekście dane słowo i zastąpić je innym, stosujmy raczej funkcję str_replace(), której wykonywanie trwa o ponad 60% krócej.

Przykład praktyczny? Proszę bardzo – dla każdej z funkcji wywołanej pięć milionów razy czas wykonania wynosił kolejno: ereg_replace() – 26,65647 sekund, preg_replace() – 25,18324 sekund, str_replace() – 10,26872 sekund.


4. Preinkrementacja jest (minimalnie) szybsza niż postinkrementacja

Podczas postinkrementacji tworzona jest zmienna tymczasowa, podczas preinkrementacji natomiast nic takiego się nie dzieje. Dlatego też kod postaci ++$num wykona się o ponad 20% szybciej niż kod $num++.


5. Czy dobrze jest korzystać z wyrażeń regularnych?

Niekiedy nie. Stosując funkcję ctype_digit($liczba), zamiast konstrukcji ereg('[0123456789]', $liczba) dla sprawdzenia, czy zmienna jest poprawną liczbą, zyskujemy 59% czasu wykonania skryptu. Aby tego dowieść, wykonaliśmy podobny kod milion razy. Efekt? Wynik dla funkcji ereg – 2,4 sekundy, dla funkcji ctype_digit – 0,99 sekundy.


6. Używaj time() zamiast date()

Sto tysięcy wywołań obu funkcji to odpowiednio 0,057 sekundy dla time() i 19,162 sekundy dla date(). Różnica rzuca się w oczy.


7. Instrukcja intval() czy int?

Wykonanie konwersji wartości na typ integer (liczba całkowita) za pomocą instrukcji $num = int '120'jest o połowę szybsze niż w wypadku $num = intval('120').


8. Kilka dobrych rad

Oprócz wymienionych powyżej wskazówek (wpływających na wydajność skryptu) są też takie, które co prawda jedynie minimalnie przyspieszą działanie aplikacji, niemniej korzystanie z nich może stać się dobrym nawykiem. Pamiętajmy więc, że:

  • funkcja explode() działa odrobinę szybciej niż funkcja split(),

  • funkcja echo jest nieco bardziej efektywne niż print,

  • porównania wykonywane za pomocą operatora === działają wydajniej od tych wykonanych przy użyciu ==,

  • pętla do{}while przewyższa pod tym względem najwolniejszą ze wszystkich instrukcję for(){}.


Podsumowanie

Musimy niestety ostudzić zapał tych, którzy po lekturze artykułu wezmą się za swój kod, zmieniając wszędzie preg_replace() na str_replace(), a wygodne pętle for(){} na mało intuicyjne do{}while. Prawdopodobnie nawet zastosowanie wszystkich wymienionych porad nie przyspieszy na tyle zwykłej, domowej strony, by stało się to zauważalne dla użytkownika. Jednak w przyszłości, gdy przyjdzie nam przygotowywać bardziej rozbudowane skrypty dla stron obsługujących dużą liczbę wywołań, ta wiedza może okazać się bardzo pomocna. Warto więc przyswoić ją sobie już teraz. Oczywiście zebrane w artykule wskazówki nie są uniwersalnym remedium na wszystkie bolączki niezoptymalizowanego kodu. Pamiętajmy o tym, że często wąskim gardłem witryny jest baza danych, a zapytania do niej kierowane mogą nas „kosztować” ponad 90% czasu wykonywania skryptu.

Popełnianym wielokrotnie błędem jest na przykład pobieranie z bazy wszystkich rekordów, by następnie wybrać zaledwie kilka z nich za pomocą pętli for(){} – podczas gdy już w zapytaniu można było przecież zażądać tylko tych paru konkretnych wyników. Warto więc pomyśleć o optymalizacji zapytań, ich cache'owaniu lub (gdy danych jest mało) zrezygnować całkowicie z bazy i przechowywać treści w plikach tekstowych. Stosowanie tych i podobnych „dobrych praktyk” pozwoli nam programować wydajne i elastyczne aplikacje sieciowe – zarówno dziś, jak i w najbliższej przyszłości.

publikuj: Opublikuj w wykop.pl Opublikuj we flaker.pl Opublikuj na OSnews.pl Opublikuj w delicious wydrukuj
17 skomentuj »

Polecamy

Reklama

Komentarze

  • miklosz

    #1 miklosz® 2008-09-30 10:34:36 0

    Mam nadzieję, że ostatni akapit jest zapowiedzią kolejnego artykułu, który byłby znakomitym uzupełnieniem powyższego tekstu ;). Mam nawet propozycje tytułu: "Nigdy więcej > " ;)

    Ten tekst - bardzo ciekawy i przydatny,ale przykład z pętlami pokazuje najlepiej, że to co najbardziej wydajne, niekoniecznie jest najprostsze/najwygodniejsze.

    Można by jeszcze coś wspomnień o korzystaniu ze zmiennych globalnych zamiast wielokrotnych zapytan do sql, konstruowania odpowiednich funkcji itp.

    None

  • dAREuS

    #2 dAREuS® 2008-09-30 10:49:43 0

    Tak, będziemy regularnie zamieszczali materiały poświęcone optymalizacji. Jeśli ktoś ma jakąś propozycję lub tekst w głowie, proszę o list na adres e-mailowy redakcji.

    None

  • tcpl

    #3 tcpl 2008-09-30 10:58:06 0

    Jesli chodzi o przyspieszanie, to juz w pierwszym przykladzie nie nalezy zapominac, ze lepiej uzyc ++$a zamiast $a++. Jak wiadomo w przypadku $a++ system musi utworzyc dodatkowa tymczasowa zmienna, ktora w przypadku zastosowania w petli for nie ma zadnego zastosowania.

    None

  • mario

    #4 mario® 2008-09-30 11:35:47 0

    Po moich doświadczeniach z optymalizacją mam kilka wskazowek, może się przydadzą:

    1) analiza problemu - trzeba rozsądnie podejść do optymalizacji i nie tracić czasu na przyspieszenie nawet kilkuset procentowe kodu który wykonuje się ułamek czasu pracy skryptu. Skupiamy się tylko na najwolniejszych częściach. Przyśpieszenie dla 100 tys powtorzeń pętli - kto ma potrzebę wykonać tyle razy kod w pętli?

    2) prostota - używajmy najprostrzych metod lub narzędzi do wykonania zadania. Nie korzystajmy np z systemów szablonów lub innych technik programistycznych tam gdzie nie jest to podyktowane innymi względami. Narzędzia dedykowane są z reguły szybsze gdyż wykonują tylko to co niezbędne a nie martwią się o to co by było gdyby :)

    Optymalizacja to proces usprawnienia tego co mamy a nie myślenie o tym co będziemy mieli kiedyś (chodzi o funkcjonalność).

    3) zyski i straty - w przyrodzie nie ma nic za darmo. To samo jest z optymalizacja.

    Można optymalizować programy pod wieloma względami: szybkości wykonania, zajmowanej pamięci, zasobów, objętości kodu.

    Nie da się zrobić wszystkiego w jednym :)

    Wybierzmy to co nam najbardziej potrzebne. Buforowanie przyśpiesza ale jednocześnie zwiększa zapotrzebowanie na pamięć.

    Bardziej efektywne algorytmy mogą być trudniejsze w zrozumieniu.

    Proces optymalizacji to bardzo złożone zagadnienie i można wiele się nauczyć ekperymentując. Zachęcam do prób na praktycznych problemach gdyż syntetyczne testy typu pętla 100 tys powtórzeń mogą trochę wypaczyć sens optymalizacji.

    Pozdrawiam

    Mariusz

    None

  • eRIZ

    #5 eRIZ® 2008-09-30 18:34:17 0

    for najwolniejsza? Bardziej bym skupił się na zastępowaniu NAJWOLNIEJSZEJ foreach wydajniejszymi rozwiązaniami.

    A tak btw: http://www.php.lt/benchmark/phpbench.php ;]

    None

  • Integral

    #6 Integral® 2008-09-30 21:41:02 0

    Ciekawy, choć krótki artykulik.

    Jednak bardzo mi się podoba, że będą kolejne, bo optymalizacji nigdy za wiele.

    Mam nadzieję, że też pojawią się sposoby optymalizacji obiektowo zorientowanych aplikacji.

    None

  • tomal

    #7 tomal 2008-10-01 21:33:10 0

    Witam,posiadamy bardzo wartosciowe domeny na sprzedaż.

    Igrzyska zimowe Kanada '2010 juz niebawem...

    Domeny na sprzedaż :

    canada2010.pl

    canada2010.com.pl

    canada2010.co.uk

    Jutro rusza strona info pod adresem : www.canada2010.pl

    Życzę sukcesów.

    None

  • mishell

    #8 mishell 2008-10-10 21:15:09 0

    można zrobić też tak:

    for($i=0, $n=sizeof($array); $i<$n;$i++) {

    rób

    }

    None

  • cbagov

    #9 cbagov 2008-10-26 15:43:37 0

    Przede wszystkim petla for czy do nie istnieje sama dla siebie. Takze optymalizacja JEJ nie jest zadnym miernikiem sukcesu.

    Tak jak i pozostale porady.

    Dla programisty nie powinna istniec alternatywa - preg_replace czy str_replace zanim nie okresli faktycznie realizowanego zadania.

    Zastosowanie i przeznaczenie polaczone z analiza problemu dopiero pozwala WYBRAC wlasciwa metode.

    I taki powinien byc moral a nie ten znajdujacy sie w owtatnim akapicie.

    Potem na forum dzieci kloca sie, ze ten srobil preg_ a ten str_ a i tak ich rozwiazanie jest do bani bo nie dokonali analizy.

    None

  • ayeo

    #10 ayeo 2008-11-09 17:56:59 0

    @miklosz, tak - wykorzystanie zmiennych globalnych to genialny pomysł!

    A co do tematu to najfajniejsze jest 15 poziomowe zagnieżdżanie foreach. Pozdrawiam!

    None

  • Piotr Jankowski

    #11 Piotr Jankowski 2008-11-09 19:04:39 0

    Stosowanie unset() nie zawsze jest zalecane. Zależy czy optymalizujemy pod kątem pamięci, czy szybkości działania. Jeśli celem jest szybkość to nie stosujmy unset(), bo osiągniemy przeciwny rezultat. Wszystko i tak pod koniec zostanie automatycznie zwolnione. Pamiętajmy że to skrypt o określonym celu, a nie aplikacja desktopowa.

    None

  • Kubi

    #12 Kubi 2008-11-09 19:38:22 0

    W pierwszej fazie pisania kodu nie należy zawracać sobie głowy ŻADNĄ optymalizacją. Zwykle przez około 90% czasu pracy wykonuje się zaledwie 10% kodu więc optymalizacja wszystkiego to strata czasu i odwraca uwagę od innych ważnych kwestii. Później można kombinować.

    None

  • IvanBarazniew

    #13 IvanBarazniew 2008-11-09 21:38:50 0

    Osobiście zgadzam się z poniższymi zdaniami:

    “More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity.” - W.A. Wulf

    “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.” - Donald Knuth

    “The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson

    Źródło en.wiki

    None

  • Piotr

    #14 Piotr 2008-11-09 22:26:07 0

    I to



    for($a = 0; $a < $size; $a++) {

    // (…)

    }
    ma być już zoptymalizowane? hm :) nie rozśmieszajce mnie.



    for ($a=0; $a < $size; ++$a) {

    // (…)

    }
    lub bardziej trywialne



    for ($a=0; 10<$a; ++$a) {

    // do something...

    }
    Jeśli chodzi o podane przykłady, to cienizna.

    None

  • Daniel

    #15 Daniel 2008-11-10 08:58:29 0

    Korzystanie z ereg_*? Z tego co wiem, bez sensu porada: http://pornel.net/ereg

    None

  • googlebot

    #16 googlebot 2009-05-01 19:57:27 0

    wiekszego idiotyzmu nie czytalem nt replace...

    preg jest stanowczo szybszy!!!

    IP: 79.191.73.[...] Opera/9.64 (Windows NT 5.1; U; pl) Presto/2.1.1

  • darky

    #17 darky 2010-06-25 15:36:31 0

    Optymalizacja poprzez zastąpienie bazy danych plikami tekstowymi?? Nawet przy małej ilości danych połączenie z bazą i wykonanie zapytania trwa krócej niż include plików...

    Po drugie:

    $str = 'blablablabla';

    $str .= 'blablablabla'; 

    $str .= 'blablablabla'; 

    $str .= 'blablablabla';  

    echo $str;

    jest wydajniejsze od: 

    echo 'blablablabla';

    echo 'blablablabla';

    echo 'blablablabla';

    echo 'blablablabla';

    Pozdrawiam

    IP: 89.229.35.[...] Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.5.24 Version/10.53

Uwaga! Możesz zarejestrować się w serwisie i w ten sposób zarezerwować swój nick oraz ominąć konieczność ciągłego odczytywania wyrazów.

Aby dodać komentarz, musisz podać swój nick, treść komentarza oraz poprawnie przepisać oba słowa z obrazka (słowa muszą być rozdzielone spacją).
W treści komentarza można używać języka formatowania BBcode.

Polecane książki

Czytaj Webhosting

Chcesz być na bieżąco z naszymi informacjami? Zapisz się na Newsletter.

Zarejestruj domenę

Sprawdź dostępność swojej domeny:

.pl: 0 zł   .com: 19.90 zł
.com.pl: 0 zł   .eu: 19.90 zł