Zgłaszane zapotrzebowanie przez skrypty (jak i aplikacje) może być uzależnione od wielu czynników. Najczęstszymi powodami takich sytuacji są błędy w kodzie aplikacji. Choć nie zawsze jest to jedyny i decydujący czynnik.

Wykorzystanie pamięci RAM na przykładzie Wordpress

Wordpress umożliwia stworzenie prostej strony internetowej, sklepu czy też korporacyjnego portalu. Jednak końcowe wykorzystanie pamięci RAM dla poszczególnych instalacji może być krańcowo odmienne, ponieważ każda z instalacji wykorzystuje lub może wykorzystywać:

  • szablon stron, który faktycznie jest skryptem PHP i w zależności od widoków i porcji danych mogą wymagać więcej pamięci RAM
  • pakiet wtyczek
  • integratory z aplikacjami zewnętrznymi
  • modyfikacje
  • wielkość obrabianych plików graficznych
  • wersja PHP
  • dane

Dwa najważniejsze czynniki to błędy w aplikacji oraz dane przechowywane przez aplikację. Rosnąca liczba rekordów w bazach danych może powodować także wzrost wykorzystania pamięci RAM/CPU samych skryptów - czasami jest to spowodowane specyfiką oprogramowania lub zwyczajnie błędów (np. brak paginacji, zwalniania wolnych zasobów itd.).

Tak samo jak samochód będzie spalał więcej paliwa w przypadku zwiększenia wagi bagaży jaki przewożonych osób, tak samo należy przyjąć zwiększone zapotrzebowanie na pamięć RAM w przypadku ilości przetwarzanych danych przez aplikację (baza sql, pliki, skrypty skórek itd.).

Skalowanie obrazków - dlaczego wymaga tak dużo pamięci

Obróbka grafiki to najbardziej zasobożerna funkcja aplikacji. Można łatwo policzyć aby dokonać konwersji obrazka o rozmiarze 1024 x 768 pikseli na 800 x 600 zajmie minimum (1024*768*x) + (800*600*x) bajtów. Gdzie x to wielkość palety barw, x może wynieść 1 (do 255 kolorów), 2 (do 65535 kolorów) lub 4 (powyżej 65535 kolorów).

Wielkość palety barw nie oznacza, że np. obrazek musi wykorzystywać 60 tyś kolorów. Jeżeli obrazek wykorzystuje tylko jeden kolor ale z palety w zakresie kolorów od 0 do 65535 (o numerze id np. 10000) to wykorzystanie palety barw będzie wynosiło właśnie 65535, czyli każdy piksel będzie ważył 2 bajty.

Zdjęcia oddające idealną fotografie, zapisane są w palecie wykorzystującej około 16 milionów barw. Dlatego zapis zdjęcia o rozmiarze 2816 x 2112 (5,95 megapixeli) w palecie 16 milionów barw, wykorzysta 4 bajty na każdy piksel; (2816* 2112 * 4) = 23789568 bajtów = 23,8 MB. Pliki graficzne stosują kompresję, jednak wykorzystanie RAM dla obrazków graficznych zawsze jest w wersji rozpakowanej. Dlatego bez względu na rozmiar pliku .jpg, który może zmniejszyć rozmiar pliku wielokrotnie, w pamięci RAM zawsze zajmie tyle bajtów: wysokość * szerokość * liczba bajtów wykorzystanych przez paletę barw.

Oczywiście to tylko mocno przybliżone wartości nie zawierające innych składowych programu, jednak widać że wykorzystanie RAM przy dużych obrazkach może być gigantyczne

Integratory z aplikacjami zewnętrznymi

W wielu przypadkach, część kodu odpowiedzialna za komunikację i wymianę danych pomiędzy Twoją aplikacją a np. porównywarką cen lub innym systemem pożera w trakcie „rozmowy” najwięcej pamięci RAM. Wielkość wykorzystywanej pamięci RAM może w takiej sytuacji nie zależeć w 100% od Twojej aplikacji i jej wykorzystanie może być wyraźnie różne w poszczególnych sesjach.

Zwiększone wykorzystanie RAM przy komunikacji z serwerami zewnętrznymi uzależnione jest zawartością przesyłanych danych i odpowiedzi serwera zdalnego, który udzieli odmiennych komunikatów.

Komunikacja pomiędzy aplikacjami w formie XML, nakłada dodatkowy narzut na wykorzystanie pamięci, właśnie ze względu na wybrany format danych. XML jest świetnym językiem o bogatych możliwościach, niestety niesie ze sobą także cenę wykorzystania pamięci RAM.

Zastosowanie XML w połączeniu z WSDL niesie ogromny wzrost wydajności pisania implementacji obsługi danego serwisu zewnętrznego po stronie programisty. Jest łatwe w usuwaniu błędów i przyjemne w programowaniu. Niestety wykorzystanie RAM w przypadku WSDL jest wręcz legendarne dla zwykłych serwisów. W przypadku zastosowań korporacyjnych nikt nie widzi w tym nic zdrożonego: Cena (duże wykorzystanie RAM) = Łatwość i szybkość pisania kodu:

Wykorzystanie WSDL pozwala na podstawie pliku .wsdl wygenerować automatycznie w przeciągu ułamka sekundy niemal całą warstwę komunikacyjną aplikacji, co pozwala zaoszczędzić niekiedy setki godzin pracy programistów.

W oparciu o WSDL swoją działalność oparło wiele serwisów (ceneo.pl, allegro.pl czy amazon) oferujących możliwość integracji sklepu czy strony. Jeżeli eksportujesz swoje produktu do porównywarek cenowych, kurierów, czy też posiadasz integrację z allegro - Twój skrypt na pewno posiada implementację WSDL w Soap PHP.

Stosując komunikację międzyserwisową z wykorzystaniem WSDL/XML - przygotuj się na duże wykorzystanie zasobów.

W śród obecnych trendów widzi się powoli odchodzenie od tej formy komunikacji na rzecz lżejszych protokołów, jednak w większości dużych produktów i usług zewnętrznych jest to nadal jedna z najważniejszych form komunikacji.

Czy pamięć serwera PHP liczy się do moich limitów

To zależy :)

W przypadku Hostingu WWW, bez względu na to ile wykorzystuje sam serwer PHP do serwowania twoich skryptów, zawsze masz gwarancję wykorzystania limitu per request, który uzależniony jest od wybranego planu. Mówiąc inaczej PHP może wykorzystywać 10GB, jednak dla ciebie będzie liczona tylko ta pamięć, która zostania wykorzystana przez Twój skrypt.

Jeżeli jesteś właścicielem serwera dedykowanego lub usługi hostingu dedykowanego, to wykorzystanie Twoich skryptów + samego PHP nie może przekraczać całej dostępnej na serwerze pamięci (w przypadku hostingu dedykowanym masz zawsze określony limit). Dlatego zwiększenie limitu RAM w skryptach PHP ponad dostępną pamięć na serwerze nie spowoduje, magicznego przyrostu pamięci RAM.

Sposób kontroli pamięci przez serwer

Niestety większość aplikacji posiada wycieki pamięci, jednak sami autorzy wprowadzili pewne mechanizmy, które mogą niwelować niepożądane skutki. Obsługa PHP w trybie FPM/FAST-CGI co określoną liczbę wywołań restartuje procesy PHP, dzięki temu zmniejsza ryzyko zapchania pamięci serwera i doprowadzenia do nieoczekiwanych skutków działania całego serwera.

Wyciek pamięci przez PHP jest kontrolowany w następującej kolejności

  1. PHP sprawdza czy skrypt nie wykorzystał pamięci ponad limit przyznany przez administratora. Jeżeli skrypt wykorzystuje zbyt dużo pamięci, nasze skrypty kończą swoją pracę komunikatem Fatal error: Allowed memory size of XXXX bytes exhausted (tried to allocate XXXXX) Ta sytuacja oznacza fizyczne wykorzystanie pamięci przez twoje skrypty - nie samą pracę PHP. Jest to w miarę bezpieczna sytuacja, ponieważ nie dochodzi do naruszenia pracy serwera.

  2. Serwer procesów PHP dla danego użytkownika, kontroluje liczbę wywołań (tzw. requestów) i co określony czas, restartuje wszystkie procesy danego użytkownika, które były wywołane X razy. Zapobiega to wystąpienia zdarzenia opisanego w kroku nr 3 i 4. Chwila restartu procesów PHP jest praktycznie niezauważalna dla odwiedzającego, ponieważ restartowane są procesy w danej chwili nie wykorzystywane (chyba że posiadamy bardzo duży ruch na naszej stronie w stosunku do małej ilości wykupionych zasobów). Objawem tej sytuacji może być długie i ciągłe czekanie na odpowiedź serwera (często zakończone błędem internal server error). W tej sytuacji nie następuje żaden „ludzki” komunikat, ponieważ skrypty kończą swoją pracę nieoczekiwanie.

  3. Limity systemowe pilnują aby, żaden proces nie wykorzystał więcej zasobów niżeli fizycznie zostało to przyznane dla całego konta hostingowego. Ponieważ przekroczenie tych zasobów może doprowadzić do niestabilnej pracy serwera fizycznego. Brak pamięci dla serwera fizycznego zakończy się zawieszeniem komputera i jedyną metodą wznowienia jego pracy będzie restart maszyny - co w takiej sytuacji może i zapewne doprowadzi do uszkodzenia zgromadzonych danych na maszynie (pliki, bazy MySQL)

  4. Supervisor maszyny wirtualnej (wszystkie konta hostingowe są umieszczone w pojedynczych maszynach wirtualnych lub w małych grupach w celu zminimalizowania skutków działań w przypadku awarii) w przypadku stwierdzenia nieprawidłowego zachowania maszyny wirtualnej restartuje ją. Sytuacja ma miejsce jeśli np. wszystkie poprzednie zabezpieczenia nie wystarczyły. Zdarzenie takie, powoduje, że jedynym komunikatem jaki może zobaczyć użytkownik przez kilka sekund to komunikat Internal Server Error lub informacja w przeglądarce, że host nie odpowiada.

  5. Zawieszenie się serwera fizycznego.

Podsumowując komunikat Fatal error: Allowed memory size of XXXX bytes exhausted (tried to allocate XXXXX) jest spowodowany wykorzystaniem pamięci RAM przez Twoje skrypty - nie błędy systemu Linux czy też innych aplikacji serwerowych. Błędy systemowe mają znacznie bardziej tragiczny przebieg i nie należy oczekiwać w takiej sytuacji jasnych i klarownych komunikatów

Oczywiście, komunikat Internal Server Error nie oznacza, sytuacji spowodowanej przekroczonej ilości pamięci RAM. Jest to sytuacja w której serwer panuje jeszcze nad błędami powodowanymi przez oprogramowanie użytkownika.

Ile pamięci RAM dla mojej strony

Poniżej przedstawiamy uśrednione wartości pamięci RAM dla poszczególnych aplikacji - proszę pamiętać, że każdy przypadek jest różny, jednak zachowanie tych wartości pozwala pracować wielu aplikacjom poprawnie.

  • 100 MB proste skrypty
  • 200 MB Systemy CMS bez dodatków (Wordpress, Joomla)
  • min. 500 MB skrypty zajmujące się przetwarzaniem obrazów (np. strona fotografa, na którą wgrywane są obrazki o dużych rozmiarach z wykorzystaniem wysokiej palety barw).

Należy przyjąć, iż sklepy internetowe, systemy CMS wraz z dodatkami instalowanymi oddzielnie (po zainstalowaniu samego sklepu czy Wordpressa) mogą wymagać do poprawnej pracy min. 500 MB. Z naszego doświadczenia wynika, iż sklepy często wymagają jeszcze więcej pamięci RAM od 1 do 2 GB do poprawnego działania.

Są to wartości szacunkowe, jednak na bazie wieloletnich doświadczeń oraz obserwacji działania i wykorzystania zasobów kilkudziesięciu tysięcy serwisów, pozwalają nam często wybrać optymalne środowiska dla klientów, którzy zdecydują się skorzystać z naszego doradztwa w tym zakresie.

Pamiętaj, że przestawione wartości nie są stałymi i mogą wahać się przy określonej odwiedzalności lub zawartości baz danych. Napewno jednak należy przyjąć, że wraz z przyrostem danych będzie także rosło zapotrzebowanie na pamięć RAM i moc CPU.

Więcej na temat Fatal error: Allowed memory size of XXXX bytes exhausted (tried to allocate XXXXX) przeczytasz tutaj