Translate: 
EnglishFrenchGermanItalianPolishPortugueseRussianSpanish

Drupal i HipHop for PHP – część I: kompilacja

Tuż po upublicznieniu HipHop for PHP w Internecie pojawiło się wiele artykułów na temat tego kompilatora oraz możliwości jakie może zaoferować istniejącym skryptom PHP. Większość z tych tekstów opisywało jednak problemy, które uniemożliwiały skompilowanie dwóch najpopularniejszych systemów CMS Drupal, i Joomla. Operacja kończyła się niepowodzeniem z powodu złej jakości kodu PHP, w który zostały napisane oba systemu.

Informacje zawarte we wspomnianych artykułach są już jednak nieaktualne: od czasu ich publikacji pojawiły się nowe wersje obu systemów CMS, mianowicie Drupal 7 oraz Joomla 1.6.

Czy w nowych wersjach poprawiła się jakość kodu PHP? Czy system Drupal można już bez problemu skompilować? Niniejsza seria artykułów odpowie na te pytania.

Informacje wstępne

Testom poddałem system Drupal 7.0. Do przechowywania danych użyłem bazy MySQL 5.1.47. Baza oraz skrypty PHP były zainstalowane na jednym serwerze testowym pracującym pod kontrolą systemu Fedora 12.

Do kompilacji posłużyłem się najnowszą (na dzień 29.04.2011) wersją kompilatora HipHop for PHP (sposób jego instalacji opisany jest w tym artykule).

Lista plików systemu Drupal

W celu przeprowadzenia testów musiałem najpierw wygenerować listę plików do skompilowania. Potrzebne informacje znalazłem w pliku htaccess dostarczonym razem z systemem Drupal. Posiada on w sobie wszystkie rozszerzenia plików, w których znajduje się kod PHP.

Do wygenerowania listy plików PHP posłużyłem się następującym poleceniem:

cd drupal
find . \( -name "*.php" -o -name "*.engine" -o -name "*.inc" -o -name "*.info" -o -name "*.install" -o -name "*.module" -o -name "*.profile" -o -name "*.test" -o -name "*.theme" -o -name "*.tpl" \) > files.list

Przyznaję, że powyższa lista wzbudziła we mnie mieszane uczucia. Na systemie Drupal pracowałem kilka lat temu i widziałem strukturę jego plików, nie spodziewałem się jednak aż tylu różnych rozszerzeń, w których może być przechowywany kod PHP. Dla jednych osób jest to kwestia przyzwyczajenia, dla innych utrudnienie w utrzymaniu systemu.

Kompilacja kodu PHP

Aby przyspieszyć kompilację kodu wpisałem następujące polecenie:

export MAKEOPTS=' -j4 '

Ustawienie zmiennej $MAKEOPTS na wartość „-j4″ wymusza na kompilatorze HipHop for PHP kompilowanie skryptów PHP w czterech równoległych procesach cc1plus. Przy doborze wartości należy brać pod uwagę ilość dostępnej pamięci RAM oraz liczbę procesorów na serwerze (przy podanej wartości zalecane wymagania sprzętowe to 2GB ramu oraz 4 CPU).

Innym sposobem przyspieszającym kompilację kodu jest użycie programu distcc, przeznaczonego do dystrybucji kompilacji przez sieć do innych komputerów (z uwagi na ograniczenia sprzętowe opiszę ten mechanizm w innym artykule).

Do skompilowania systemu Drupal uruchomiłem następujące polecenia w jego katalogu domowym:

date && ~/hiphop/hiphop-php/src/hphp/hphp\
 --keep-tempdir=1 \
 --log=3 \
 --input-list=files.list \
 --include-path="." \
 --force=1 \
 --cluster-count=16 \
 -v "AllDynamic=true" \
 -v "AllVolatile=true"

Ponieważ kompilowanie na serwerze testowym trwało około 13 minut, użyłem polecenia date aby na podstawie otrzymanej godziny obliczać czas pozostały do zakończenia operacji.

Oto opis użytych przełączników:

  1. –keep-tempdir=1
    Wymusza zachowanie katalogu tymczasowego, w którym został skompilowany skrypt PHP. Udostępnia to między innymi możliwość podejrzenia kodów źródłowych w języku C++ wygenerowanych przez HipHop for PHP.
  2. –log=3
    Zwiększa poziom raportowania czynności, jakie wykonuje HipHop for PHP podczas kompilowania kodu.
  3. –input-list=files.list
    Wczytuje z pliku files.list listę skryptów PHP do skompilowania.
  4. –force=1
    Wymusza kompilację kodu, niezależnie od znalezionych w nim błędów. Bez tego przełącznika HipHop for PHP przerywa kompilowanie skryptu, gdy tylko znajdzie w nim niedozwolone funkcje (np. eval()) lub inne błędy kodu (nawet jeśli nie zostaną później uruchomione). Znalezione błędy można później odczytać z pliku CodeError.js, który zostanie zapisany w katalogu z plikiem wykonywalnym.

  5. –include-path=”.”
    Wskazuje bieżący katalog jako katalog, od którego mają zaczynać się ścieżki dla includowanych przez PHP plików.
  6. -v „AllDynamic=true”
    Włącza obsługę dynamicznego wywoływania funkcji (np. poprzez call_user_func()). Użycie tego przełącznika wpływa negatywnie na wydajność aplikacji.
  7. -v „AllVolatile=true”
    Pozwala na dynamiczne deklarowanie klas i funkcji (używane w warunkach: if(!class_exists(„Test”)) { }). Należy używać tego przełącznika tylko gdy kompilowany kod PHP tego wymaga. Włączenie tej opcji obniża wydajność skompilowanego programu.
  8. –cluster-count=16
    Bez tego przełącznika każdemu plikowi PHP odpowiada jeden plik *.cpp. W przypadku projektów składających się z bardzo dużej ilości plików z kodem wpływa to negatywnie na wydajność kompilatora. Wartość 16 przekazana do przełącznika cluster-count włącza grupowanie skryptów PHP do maksymalnie plików 16 *.cpp. Właściwa wartość przyspiesza kompilowanie równoległe (czy to lokalne, czy też poprzez distcc).

Uruchomienie systemów CMS

System Drupal musi działać jako serwer HTTP. Na szczęście w przypadku kompilatora HipHop for PHP nie jest to żadnym problemem. Zależnie od argumentów wejściowych skompilowane skrypty PHP mogą być uruchomione w dwóch różnych trybach: jako aplikacje konsolowe (domyślnie) lub serwery HTTP (przełącznik -m „server”):

/tmp/hphp_AJSp1P/program -m server -p 8080 \
 -v "Server.SourceRoot=`pwd`" \ 
 -v "Server.DefaultDocument=index.php" \
 -v "Log.Level=Verbose" \
 -v "Log.NoSilencer=true" \
 -v "Log.AlwaysLogUnhandledExceptions=true" \
 -c $HPHP_HOME/bin/mime.hdf &

Ścieżka /tmp/hphp_AJSp1P/program jest tymczasowa i wskazuje na program, który został wygenerowany przez HipHop for PHP. Po każdej kompilacji nazwa katalogu ulega zmianie, należy więc pamiętać o jej zmianie podczas próby uruchomienia aplikacji.

Wyjaśnień wymagają następujące przełączniki programu:

  1. -p 8080
    Uruchamia serwer HTTP na porcie 8080.
  2. -v „Server.SourceRoot=`pwd`”
    Pozwala oszukać skompilowane skrypty PHP tak, by podczas używania funkcji realpath() były informowane, że zostały uruchomione w katalogu, w którym jest nieskompilowany system CMS (pomimo tego, że pliki wykonywalne znajdują się w innym miejscu).
  3. -v „Server.DefaultDocument=index.php”
    Ustawia index.php jako domyślny plik uruchamiany podczas obsługi krótkich adresów URL (np: http://localhost/).
  4. -v „Log.Level=Verbose”
    Włącza najbardziej szczegółowy stopień logowania zdarzeń PHP w skompilowanym skrypcie. Ułatwia to debugowanie źle napisanych aplikacji.
  5. -v „Log.NoSilencer=true” \
    Wymusza raportowanie błędów i ostrzeżeń także w przypadku, gdy były ignorowane w kodzie operatorem „@”.
    Jest to bardzo przydatna opcja gdy przewidujemy problemy ze skompilowanym programem.
  6. -v „Log.AlwaysLogUnhandledExceptions=true”
    Włącza logowanie wszystkich nieobsłużonych wyjątków. Mechanizm ten sprawdza się doskonale w przypadku, gdy aplikacja PHP nie obsłużyła wyjątku ale posiadała własną obsługę błędów (funkcja set_error_handler()) ignorującą te zdarzenie.
  7. -c $HPHP_HOME/bin/mime.hdf
    Wczytuje do serwera HTTP listę typów MIME dla plików, które będą przesyłane do użytkownika. Bez tego polecenia grafika oraz style CSS nie będą się poprawnie wczytywać w przeglądarce WWW.

Jak łatwo zauważyć, przed uruchomieniem aplikacji włączyłem większość flag debugu. Jest to spowodowane poważną obawą o problemy z uruchomieniem tego systemu CMS.

Test systemu Drupal

Po skompilowaniu skryptów oraz uruchomieniu serwera HTTP przyszedł czas na testy. Do szybkiego sprawdzenia wystarczy polecenie:

curl http://127.0.0.1:8080/

Niestety po wykonaniu tego polecenia naszym oczom pokaże się pusta strona, a w logach aplikacji pojawią się błędy krytyczne. Okazuje się, że nadal kod źródłowy systemu Drupal nie jest kompatybilny z kompilatorem HipHop for PHP. Do uruchomienia strony wymagana jest więc modyfikacja orygonalnego kodu i ponowne skompilowanie projektu.

W następnych artykułach opiszę napotkane problemy z kompatybilnością PHP które uniemożliwiły skompilowanie systemu oraz konieczne modyfikacje kodu, umożliwiające jego uruchomienie.

Tagi: , , ,

Dodaj odpowiedź