Zend Framework to oczywiście najlepszy framework php ;) ale ma bardzo duże problemy co do wydajności. Przy prostych stronach można to jeszcze przeżyć, ale dla aplikacji, które są przewidziane na duże obciążenie staje się to już drzazgą w tyłku.

Na pierwszy ogień pójdzie funkcja Zend_Loader::registerAutoload() - korzystanie z niej jest bardzo wygodne, ale wpływa bardzo negatywnie na szybkość i ilość pamięci wykorzystywanej przez skrypt.

Przeprowadźmy test

Aby test miał więcej wspólnego z rzeczywistością zostanie wykonany na już przygotowanym frameworka do pracy. Z grubsza będą to:

  • Inicjacja i sprawdzenie autoryzacji na podstawie Zend_Acl (lista praw trzymana w pliku php)
  • Wykryciu i ustawieniu odpowiedniego locale (Zend_Locale)
  • Ustawienia widoku
  • Nawiązanie połączenia z bazą danych MySql
  • Ustawieniu routes na podstawie plików ini
  • Inicjacji Zend_Mail_Transport_Smtp

Akcja indexAction() jest pusta, nie jest wykonywane żadne zapytanie do bazy danych. Do profilowania kodu użyłem zmodyfikowanego Profiler’a z Magento Ecommerce. Kod został podzielony na odpowiednie bloki: application, setup, dispatch, action. Na mojej maszynie mam:

  • PHP 5.2.4
  • XDebug 2
  • Apache 2
  • MySql 5

Samych parametrów mojego komputera nie będę podawał, bo nie ma to sensu, nie będziemy zwracać uwagi na same liczby, a raczej na różnice procentowe.

zf_autoload_without_require_mini.png

Nas najbardziej interesuje pierwszy rząd  ‘Application’ obejmująca całą aplikacje. Najbardziej przykuwającą oko rzeczą jest pożerana pamięć 5MB.

Teraz przygotujemy plik require.php, który dołączamy jak najwcześniej w bootstrapie. Plik zawiera dołączenia wszystkich klas aplikacji (Zend i nasze własne), które były potrzebne do uruchomienia strony testowej.

require_once 'Zend/Session.php';
require_once 'Zend/Session/Abstract.php';
require_once 'Zend/Session/Namespace.php';
require_once 'Zend/Session/SaveHandler/Interface.php';
require_once 'Zend/Session/Exception.php';
require_once 'Zend/Exception.php';
require_once 'Zend/Acl/Role/Interface.php';
require_once 'Zend/Config.php';
itd...

zf_autoload_with_require_mi.png

Pomimo prawie 3-krotnie zmniejszonego czasu (0.25 vs 0.09), pamięć wykorzystana przez skrypt zmalała z 5 MB do 326 KB, to ponad 10-krotnie mniej!!! Nawet sobie nie wyobrażacie jaka to ulga dla serwer.

Listę plików ładowanych podczas działania aplikacji można otrzymać dzięki informacji jakie klasy zostały załadowane (w ZF jedna klasa to jeden plik), a tę informacje dostajemy dzięki funkcji get_declared_classes().

Wniosek

Na etapie tworzenia aplikacji spokojnie możemy ze względu na wygodę używać Zend_Loader::registerAutoload(), zaś już w czasie wdrażana zdecydowanie sugeruję rozwiązanie podobne do mojego.

Społeczność: Powiązane posty:

Komentarze

  1. Szymon Szczepaniak

    Warto dodać, iż w pliku require.php najlepiej dodać tylko te pliki, które są wykorzystywane przy każdym (lub w większości przypadku) żądaniu. Jeżeli zaincludujemy wszystkie to znowu możemy mieć małą nadmiarowość ;).
    Część plików można oczywiście też includować ręcznie ;)

    PS. Gratuluje determinacji i powrotu do pisania na blogu ;)

  2. PE

    Na jakiej wersji Zend Frameworka był przeprowadzany test? Jeżeli dobrze pamiętam w 1.6 zostały wprowadzone poprawki do Zend_Loader’a. Sprawdziłem przez get_declared_classes(), uzyskane wyniki prze użyciu Zend_Loadera jak i przy require’owaniu poszczególnych klas były identyczne.

  3. Hubert Marzec

    @PE Dobra uwaga. Testy były przeprowadzone na wersji 1.5.1. Będę musiał uzupełnić wpis. Przy okazji jeżeli porównujemy poszczególne wersje, to wydajność ZF z czasem spada. Porównaj np. wersje 1.0.1 z 1.6.

  4. PE

    Z braku innych narzędzi sprawdziłem pamięć przez memory_get_usage() przyznam się że wynik troszkę mnie zaskoczył:
    bez autoloadera: 4644968
    z autoloaderem: 4642872

    A co do wydajności … to wszystko zależy od tego jak się do sprawy podchodzi i co chcemy uzyskać ;)

    Może warto było by dodać małą adnotację jakieś wersji dotyczy tekst ?

  5. Hubert Marzec

    Tak, dodam adnotacje i zrobie update postu. Narazie nie mam czasu :/

  6. Wojtek

    W nowszych wersjach jeszcze lepsze wyniki może dac pozostawienie autoloadera i usunięcie we wszystich plikach ZF wywołań instrukcji require_once. Z tego co wiem to w przyszłości ma się pojawić w komponencie Zend_Tool narzędzie ułatwiające usuwanie.

  7. Hubert Marzec

    Między innymi o tym i innych sposobach przyspieszenia ZF można przeczytać tutaj

  8. Zend Framework Flex Flash AIR » Flex PHP i Zend_Amf czyli First Blood

    […] Pierwsze linijki ładują plik konfiguracyjny oraz klasy usług. Korzystam z Zend_Loadera, ponieważ przyspiesza on pisanie, ale oczywiście ma on wpływ na wydajność aplikacji o czym więcej możesz dowiedzieć tutaj DzbanyIT.  […]

Dodaj komentarz