Ile kosztuje Cię wolne działanie strony oraz dlaczego większość ludzi optymalizuje nie to co potrzeba
Jakiś czas temu zapowiedziałem pisanie od czasu do czasu artykułów typu know-how, czas więc na coś w tym temacie. Będę też wdzięczny za feedback od Was: czy tego typu teksty w ogóle Was interesują i czy chcielibyście widzieć więcej takich na Webstop? Czy również dla osób mniej technicznych (a one stanowią 50% czytelników Webstop, są to menedżerowie i właściciele biznesów webowych) ten tekst jest ciekawy i na tyle przystępnie napisany, że zrozumiały?
Jak wielu z Was zastanawia się nad tym, na ile istotna jest szybkość wyświetlania Waszej strony? Oczywiście każdy chciałby, żeby wyświetlała się szybciej, ale mało kto naprawdę się o to stara czy wręcz mierzy zmianę wyników finansowych w zależności od szybszego lub wolniejszego ładowania witryny. Ponadto większość z tych, którzy faktycznie zaprzątają sobie głowę wydajnością, podchodzi do problemu zupełnie nie od tej strony co trzeba.
Pół sekundy warte miliard dolarów rocznie
Amazon zbadał, że każde 100 milisekund opóźnienia w otwieraniu strony kosztuje ich 1% sprzedaży. Google odkryło, że gdy zwiększyło liczbę wyników wyszukiwania wyświetlanych na stronie z 10 do 30, ruch oraz przychody z reklamy spadły o 20%. Taki był koszt dodatkowej pół sekundy ładowania strony z większą liczbą wyników (wzrost z 0,4 do 0,9 sekundy). Tak drobne ułamki sekund potrafią decydować o naprawdę wielkich pieniądzach. Prawdopodobnie prowadzicie mniejsze serwisy niż Amazon czy Google, więc w Waszym przypadku straty będą odpowiednio mniejsze, ale nie znaczy to, że nie powinniście o nich myśleć.
Najczęściej nie chodzi o prędkość samej aplikacji
Jeśli jednak utożsamiacie prędkość ładowania witryny z wydajnością Waszej aplikacji działającej po stronie serwera, to jesteście w sporym błędzie. W większości serwisów czas generowania samego kodu strony to zaledwie 10-30% czasu potrzebnego na jej wyświetlenie – i o ile Wasza aplikacja nie jest potwornie wolna, powinniście skupić się na zredukowaniu tych pozostałych 70-90%. Napiszę o tym więcej poniżej.
Walka z czasem ładowania strony może być ciężka i żmudna, czasami jednak świetne efekty można uzyskać stosunkowo prostymi i tanimi metodami. Dla przykładu warto uniezależnić czas ładowania Waszej witryny od innych witryn. Wszystkie widgety czy reklame pobierane z zewnątrz mogą spowolnić Wasz serwis.
Case: Reklamy z zewnętrznego adservera
W serwisie SportoweFakty.pl, który od niedawna współtworzę, od zawsze problemem były reklamy, których czas ładowania był często znacznie dłuższy niż czas otwierania samej strony. Jako że umieszczone są w różnych częściach witryny, ich powolność wstrzymywała wyświetlanie strony przez przeglądarkę. Reklamy serwowane są przez zewnętrzny adserver domu mediowego, więc nie mieliśmy wpływu na ich szybkość. W dodatku raz na jakiś czas (stosunkowo często) adserver łapał zadyszkę i trzeba było czekać na reklamy – oraz całą stronę – bardzo długo, czasem nawet do dziesięciu sekund.
Kilka prób wyświetlania kodów reklamowych dopiero po załadowaniu całej strony spełzło na niczym – adserver najwyraźniej miał zabezpieczenia przed tym, prawdopodobnie po to, żeby nie próbować go oszukać podmieniając kilkakrotnie reklamy w trakcie trwania jednej odsłony i uzyskując w ten sposób zawyżoną liczbę wyświetleń. Wystarczył jednak jeden mój telefon do domu mediowego, żeby okazało się, że mają też inny rodzaj kodów, który działa dokładnie tak jak chcemy – czeka na wyświetlenie całej strony włącznie z wszystkimi grafikami i dopiero potem ściąga i wyświetla reklamy. Zmieniliśmy kody na inne i korzystanie ze SportoweFakty.pl nagle stało znacznie bardziej przyjemne (pamiętajcie, że o ile większość z Was, czytających Webstop, prawdopodobnie używa adblocka, tak zdecydowana większość internautów go nie używa).
Jeśli korzystacie więc u siebie na stronie z jakichkolwiek elementów zewnętrznych, w szczególności kodów reklam lub innych skryptów JavaScript, które tworzą lub modyfikują elementy DOM (w związku z czym przeglądarka musi czekać na ich wykonanie zanim wyświetli stronę), postarajcie się ładować je dopiero po wyświetleniu strony. Jeśli nie potraficie tego zrobić lub jest to niemożliwe dla danego kodu, poproście dostawcę o kod działający w inny sposób. W naszym przypadku obniżyło to przeciętny czas wyświetlania strony o połowę.
Co udało nam się osiągnąć
To oczywiście tylko jeden z detali, ale bardzo dobry przykład na to, jak istotne mogą być rzeczy, o których nie zawsze się myśli w kontekście wydajności. W SportoweFakty.pl trochę czasu spędziliśmy nad tym, żeby szybko wyświetlać stronę – wciąż mamy sporo do zrobienia i wiem o dwóch wąskich gardłach, którymi jeszcze kiedyś się zajmiemy, ale to, co udało nam się dotychczas osiągnąć, jest dosyć zadowalające. Porównałem dziś nasz wynik do innych witryn sportowych: Onetu, WP, Interii, Gazety, o2 i 90minut.pl znajdujących się w megapanelu wyżej od nas oraz pilkanozna.pl i sport24.pl będących poniżej. Użyłem Full Page Test udostępnianego przez Pingdom – bardzo dobrego narzędzia do takich zastosowań. Oto wyniki:

Testy powtórzyłem kilkakrotnie i wybrałem najczęściej powtarzające się rezultaty. Na tle firm znacznie większych i mających nieporównywalnie większe zasoby prezentujemy się całkiem nieźle (całe SportoweFakty.pl ze swoimi 20 mln odsłon miesięcznie obsługiwane są przez tylko jeden serwer. Skoro już jestem przy SportoweFakty.pl – znowu szukam kolejnych programistów do pracy przy serwisie. Jednego na stałe oraz kilku na okres 3 miesięcy).
Liczy się czas ładowania grafik, CSS, JS
To, co można zauważyć w tej tabelce, to że witryny z największą ilością osadzonych obiektów (obrazki, CSS, JavaScript, inne) mają też najdłuższe czasy ładowania strony. Zauważcie też, że wydajność samej aplikacji – czyli czas ładowania dokumentu głównego – wcale niekoniecznie musi znacząco wpływać na prędkość ładowania całej strony. Główny dokument sport.wp.pl jest generowany w 0,6 sekundy, podczas gdy na pozostałych ponad 150 obiektów czeka się kolejne 4,3 sekundy.
To są oczywiście czasy pobierania strony przez oprogramowanie Pingdom, które działa z zagranicznych serwerów – dla odwiedzających z Polski czasy będą nieco krótsze – ale większość testowanych serwisów hostowanych jest w Polsce (chyba tylko z wyjątkiem 90minut.pl), więc nie jest tak, że Pingdom do któregoś z nich miał bliżej niż do innych. W Polsce czasy mogą się nieco obniżyć, ale proporcjonalnie – bezwzględne wartości nie są tu aż tak istotne, jak stosunki między nimi.
W przypadku WP dochodzi jeszcze przekierowanie, od którego zaczyna się nasza wizyta w serwisie, a które trwa aż 0,7 sekundy! Dla porównania, podobne przekierowanie na sport.pl trwa 0,1 sekundy. W SportoweFakty.pl przekierowujemy jeśli ktoś wpisze domenę sportowefakty.pl zamiast www.sportowefakty.pl – i trwa to również 0,1 sekundy. Zupełnie nie potrafię zrozumieć w jaki sposób można usprawiedliwić aż 0,7 sekundy na zwykłe przekierowanie. W WP prawdopodobnie nikt nawet nie zaprząta sobie głowy takimi detalami, ale jeśli każdy taki detal miałby kosztować choćby 0,5% przychodów, to w tak dużej firmie na pewno warto się tym zająć.
Optymalizujcie tam, gdzie można osiągnąć największe efekty
Z tego wszystkiego wynika jeden wniosek – zanim zabierzecie się za jakiekolwiek optymalizacje, sprawdźcie dokładnie, które obszary Waszego produktu najbardziej ich wymagają. Jeśli tylko 20% czasu ładowania strony przypada na generowanie kodu HTML, dlaczego koncentrowanych jest na nim 80% wysiłków optymalizacyjnych? Większość osób, jakie znam, koncentruje się głównie na wydajności aplikacji, zapominając o wszystkim tym, co dzieje się już po wygenerowaniu kodu HTML przez oprogramowanie. Ale podczas gdy skrócić jego generowanie z 0,6 do 0,5 sekundy może być trudno i może to zająć Wam sporo czasu, tak skrócić czas ładowania pozostałych obiektów z 3 do 2,5 sekund będzie Wam prawdopodobnie znacznie łatwiej. Skoro więc osiągnięcie pięciokrotnie większego zysku jest możliwe znacznie mniejszym kosztem, dlaczego tak mało osób o tym myśli?
Zestaw dobrych praktyk
Jest kilka dobrych praktyk, które stosunkowo niskimi kosztami pozwolą Wam osiągnąć wiele w optymalizacji czasu ładowania Waszej strony.
- Zacznijcie od przeanalizowania procesu ładowania Waszej strony narzędziem na przykład takim, jakie dostarcza Pingdom.
- Używajcie lekkich, superszybkich serwerów www dla treści statycznych. Nasza-klasa, mimo iż aplikacja obsługiwana jest przez Apache, wszystkie media serwuje przez ultraszybki serwer nginx. W SportoweFakty.pl używamy równie szybkiego lighttpd. Nie jest dobrym pomysłem używanie do wyświetlania zdjęć zasobożernego i wielkiego Apache, z załadowanymi wszystkimi modułami pozwalającymi na robienie dziesiątek rzeczy, które przy wyświetlaniu plików statycznych nie są potrzebne.
- Nie usprawiedliwiajcie się liczeniem na cache przeglądarki. Yahoo sprawdziło, że 40-60% odwiedzających ich strony przychodzi z pustym cache – dlatego naprawdę warto ograniczyć liczbę wywołań HTTP.
- Używajcie nagłówków Cache-Control, ustawiając czas cache’owania treści statycznych na “nieskończoność” – to trochę zwiększy liczbę odsłon, w których przeglądarki nie będą musiały pobierać obrazków. Pamiętajcie jednak, że wówczas każda zmiana obrazka na nowy musi się wiązać ze zmianą jego URL, inaczej nie zostanie odświeżony.
- Używajcie wywołań typu GET zamiast POST dla zapytań AJAX. Tryb POST jest znacznie wolniejszy, gdyż wykonywany jest w dwóch krokach, z użyciem dwóch pakietów TCP.
- To, co nie jest absolutnie niezbędne do natychmiastowego wyświetlenia, ładujcie dopiero po wyświetleniu całej strony (np. reklamy, niektóre obrazki, itp).
- Używajcie rozsądnie cookies. Zawartość plików cookie jest wysyłana przez przeglądarkę za każdym razem, gdy pobiera ona coś z serwera. Przy każdej odsłonie, ale też i przy każdym pobraniu obrazka czy pliku CSS. Yahoo zbadało opóźnienie ładowania strony w zależności od wielkości cookie. Przy 2 kB cookie testowy dokument ładował się o 50 milisekund wolniej. 0,05 sekundy nie robi dużego wrażenia, ale jeśli wziąć pod uwagę, że testowy dokument nie miał osadzonych żadnych dodatkowych obiektów, a przeciętna strona posiada od 50 do 100 osadzonych grafik, to łącznie opóźnienie spowodowane ciasteczkami może być naprawdę duże. Niewiele potrzeba wysiłku, żeby rozsądnie dobierać czas wygasania cookies oraz ich zasięg (np. żeby dane potrzebne jedynie na stronie głównej nie były niepotrzebnie wysyłane do każdego z podserwisów/subdomen witryny).
- Używajcie osobnej subdomeny dla plików statycznych – w szczególności wszystkich obrazków. Nie tylko pozwoli to Wam uruchomić do jej obsługi osobny, superszybki serwer www, ale dzięki temu przy pobieraniu każdego z obrazków nie będą wysyłane wszystkie cookie, które pojedynczo opóźniają bardzo nieznacznie, ale przy kilkudziesięciu obrazkach na każdej stronie robi się z tego już zauważalna wartość (pamiętać musicie wtedy o odpowiednim ustawieniu zakresu cookie, żeby nie były wysyłane do wszystkich subdomen *.waszserwis.pl).
Ograniczcie liczbę wywołań HTTP, czyli liczbę obiektów na Waszej stronie. Jeśli Wasza strona pobiera kilka lub wręcz kilkanaście plików CSS lub JS, spróbujcie połączyć je w kilka większych, a idealnie w jeden CSS i jeden JS. Możecie pomyśleć o ograniczeniu liczby ładowanych grafik używając CSS Sprites.
Po jeszcze więcej dobrych praktyk odsyłam Was do Yahoo, którego inżynierowie bardzo dużo napisali już na ten temat. Trochę ciekawych rzeczy znaleźć można też na Yahoo UI Blog – tam wśród wielu innych zagadnień związanych z UI pojawiają się też od czasu do czasu tematy związane z jego wydajnością.
Oczywiście nie chodzi o to, żeby stosować się do wszystkich zalecanych praktyk. Zidentyfikujcie te, które w Waszym przypadku pozwolą na największy zysk najniższymi kosztami i zacznijcie od nich. Nie zawsze też w ogóle będzie warto inwestować czas w takie praktyki. Jeśli jednak macie stosunkowo spory ruch albo jeśli zależy Wam na jak najszybszym doganianiu konkurencji, każde 3% więcej przychodów lub ruchu będzie dla Was warte wysiłku.
Przeczytaj także:
- Ogłoszenie: Szukam myślących programistów PHP z pasją
- Amazon CloudFront, czyli proste CDN “dla ubogich”
- Ile osób w Polsce używa Google Chrome
- Jak skutecznie wypromować startup w niestandardowy sposób
- Śledź ogień olimpijski na Google Maps
Komentarze (30):
Dyskusja na innych blogach (trackbacks):
- Skrócenie czasu ładowania stron WWW — optymalizacja skryptów - WebFocus
- Rezygnacja z Woopry |
- Amazon CloudFront, czyli proste CDN “dla ubogich” - Webstop.pl


Ostatnio mój blog działał koszmarnie wolno, i dosyć długo siedziałem nad optymalizacją. Niestety nic nie poprawiało szybkości ładowania strony, aby była zadowalająca. W końcu pomogła pewna rzecz: usunięcie połowy wpisów z bazy danych (wszelkie zapisy nieaktywnych wtyczek i pozostałości po wcześniejszych wersjach WordPressa). Od tego czasu działa bardzo dobrze. A, i wiele wtyczek także bardzo spowalnia ładowanie się strony czy panelu administracyjnego – np (c)Feed z włączonym pokazywaniem informacji na kokpicie kto nas plagiatuje.
Ciekawy tekst. Myślałem o wydzieleniu subdomeny na statyczny kontent. Obecnie używam lighty do grafiki i CSS ale przez proxy apache, tj. ruch na statyczne katalogi kierowany jest do lighty.
do ostatniego punktu (o uzywaniu osobnej domeny na statyczne pliki) moge dopisac jeszcze inny, imo duzo wazniejszy powód: mianowicie kazda przegladarka ma limit ilosci jednoczesnych polaczen z dana domena. w takim wypadku umieszczanie zasobow na innych domenach potrafi przyspieszyc proces wyswietlania strony, gdyz wiecej elementow strony moze sie ladowac w tym samym czasie.
@kmb: Masz rację z limitem, ale samo wydzielenie grafik na osobną domenę niewiele tu zmieni. Wciąż wszystkie zasoby statyczne będą ładowane z jednego miejsca, więc nie zwiększy to ilości równoległych połączeń. Rozwiązaniem jest tutaj uruchomienie kilku serwerów/domen i równomierne rozłożenie pomiędzy nie wywołań – dzięki temu liczba pobieranych równolegle plików wzrośnie.
Ten trick i wiele innych można znaleźć pod zalinkowanym zasobem Yahoo. Napisałem o kilku moim zdaniem najistotniejszych, więcej znajdziecie na Yahoo :).
Artykuł bardzo ciekawy – jak najbardziej publikuj więcej o podobnym charakterze.
W kwestii ładowania stron: na własnej skórze odczułem jak wpływa to na zarobki, które przy problemach z serwerami zewnętrznych statystyk spadły o około 20-30% w ciągu doby – mimo że strona działała, ale ładowała się kilka sekund dłużej.
@bartek yep, dokladnie. 1 domena wiele nie da, ale 2 juz dadzą. nawet jesli rzeczywiscie te domeny wskazuja na ten sam serwer.
Fajny artykuł. Dobrym programem jest również firebug. Pozwala przeanalizować proces ładowania strony.
ciekawy i treściwy post, dzięki!
Ciekawy wpis, cieszę się że idziesz też trochę w tym kierunku ze swoim blogiem ;)
Co do wykorzystania subdomeny do obrazków, dla jakich stron warto się już w to bawić? Chodzi mi o czas wczytywania tej strony, wielkość plików do ściągnięcia albo liczę uu dziennie.
Firebug może wiele podpowiedzieć, zobaczyć ile i jakiś requestów HTTP było wykonanych przy ładowaniu dokumentu. Do aplikacji napisanych w Rails warto zainteresować się http://www.newrelic.com/RPM.html
Polecam też książkę High Performance Websites, pisana przez inżyniera z Yahoo!, można wyczytać kilka ciekawych sztuczek
Świetny wpis. Oby więcej takich
Drogi Bartku
Na waszym miejscu zainwestowalbym w wypozycjonowanie strony.
Bardzo dobry artykuł. Wspomniałbym jeszcze o dwóch sprawach:
1. Należy stosować kompresję gzip, o ile to możliwe.
2. O ile się nie mylę, to dokumenty parsowane jako xml są tylko jednokrotnie. A więc wysłanie xhtml z poprawnym nagłówkiem application/xhtml+xml (nota bene tak powinno być w wersji DOCTYPE strict) spowoduje to, że przeglądarka będzie parsować dokument tylko raz. W przypadku tradycyjnego text/html dwa razy. A więc to też ma wpływ na szybkość niejako działania witryny.
Tak, porownujmy nasze blogi do Amazona czy Google :)
My NIC nie tracimy na tym, czy strona sie bedzie wczytywac o nawet te 3 sekundy dluzej. Kogo tu oszukiwac?
Bardzo podoba mi się nowa tematyka wpisów. Czekam na kolejne…
@Chris: tracimy, ilość czytelników, 3 sekundy to wieczność!
@Chris: nie każdy posiada tylko “blogaska”..
Warto obejrzeć jak to robią giganci:
High Performance Web Sites and YSlow
http://www.youtube.com/watch?v=BTHvs3V8DBA
Google IO 2008 – Even Faster Websites
http://www.youtube.com/watch?v=QRUqVyP27Hw
i poczytać “High Performance Web Sites Essential Knowledge for Frontend Engineers” Steva Soudersa
Osiagnalem zgola odmienne wyniki od tu przedstawionych i pozwole je sobie zacytowac. Mierzylem czasomierzem dostepnym w Operze, wiec oczywista sprawa, ze moge byc mniej dokladny niz skrypt na serwerze, aczkolwiek moje wyniki cos jednak obrazją. Moje lacze to 20 Mbit z UPC.
SportoweFakty – 12 sekund
Onet Sport – 5 sekund
Sport.pl – 14 sekund
Sportfan – 3 sekundy
Polkanozna.pl – 7 sekund
Sport.Interia.pl – 16 sekund
90minut.pl – w ogole sie nie otwiera w tym momencie
sport.wp.pl – 6 sekund
Sport24.pl – 9 sekund
Nie jestem fanem sportu, wiec zadnej z tych stron nie mialem w cache. Adres wpisywalem “z palca”, czas jest mierzony od klepniecia w enter az do czasu kiedy _cala_ strona sie zaladuje.
Obrazują*
Przepraszam za literówkę.
“Tryb POST jest znacznie wolniejszy, gdyż wykonywany jest w dwóch krokach, z użyciem dwóch pakietów TCP.”
Khe? Możesz rozwinąć/dać linka do uzasadnienia? IMHO to nieprawda.
Z POST to (pół)nieprawda. Małe zapytania są przesyłane za jednym podejściem. Dopiero bardzo duże formularze i uploady plików są robione w dwóch zapytaniach z użyciem expect+statusu HTTP 100.
Podsumowując: zalecenie używania POST zamiast GET, bo POST jest (znacznie) wolniejszy jest fałszywe.
@karols: Proszę bardzo rozwinięcie + link:
http://developer.yahoo.com/performance/rules.html#ajax_get
Chcialem powiedziec ze czasy wczytu stron nie sa czasami realnymi lecz wynikiem dzialan analitykow ktorzy okreslili sredni czas wczytu biorac pod uwage rozne argumenty w tym znaczenie przegladarek i łacz….
Świetny artykuł, oby takich jak najwięcej :)
co do podpunktu o czasie cache-u to nie do konca tak jest bo za kazdym razem bedzie wysylane zadanie potwierdzenia pliku ETag (entity tag),a nie od razu zadanie pliku przez co mozna troche zaoszczedzic na odpowiedz w stylu “tak ten plik jest aktualny” zamiast wysylac caly plik od nowa. To co piszesz o zmianie adresu url to raczej (pół)nieprawda jak pilas to jeden z kL
moze troche pozno na komentarz do artylulu sprzed kilku lat, jednak tools.pingdom.com chyba nie rozumie zadan rownoleglych, bo po zmianie sposobu parsowania strony (kilka serwerow i domen) pokazuje dluzszy czas ladowania niz przy jednaj domenie /serwerze.
Narzedzie google “page speed” (wtyczka do firefoxa) podaje prawidlowe wyniki – czyli krotsze czasy ladowania.
To tylko tak na marginesie