Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Zasady pisania na forum Pro

Tematy na forum Pro mogą zakładać jedynie moderatorzy. W otwartych tematach może pisać każdy, kto ma coś fachowego do powiedzenia. Wszystkie posty nie wnoszące nic do tematu będą natychmiast usuwane, a ich autorzy dostaną ostrzeżenie.
Jeśli uważasz, że jakiś temat jest warty dyskusji na tym forum, zgłoś go w temacie Propozycje.

10 Stron V  « < 8 9 10  
Reply to this topicStart new topic
> Włączanie plików + autoloader, chętnie bym posłuchał ciekawych pomysłów
kaniagandzowski
post 27.08.2007, 18:05:25
Post #181





Grupa: Zarejestrowani
Postów: 72
Pomógł: 1
Dołączył: 2.06.2006

Ostrzeżenie: (0%)
-----


W klasie ClassLoader autora DjKermit brakuje warunku, który by nie przeglądał katalogów powstałych przez stosowanie programów do kontroli wersji np subversion.
Ponieważ gdy używa się kontroli wersji w każdym katalogu tworzy katalog .svn i w nich pliki.

I gdy próbuje się ładować wyskakuje błąd iż jest drugi raz ładowany plik.
Fatal error: Cannot redeclare class nazwaKlasy

Rozwiązałem poprzez dodanie warunku nie pozwalający przeglądać katalogi .svn lecz nie jestem autorem i nie poświęcałem uwagi gdzie powinno w sumie być jakiś dany warunek, który by nie ładował plików programu subversion.

  1. <?php
  2. private function readDir($path) {
  3. if ($handle = opendir($path)) {
  4. while (($file = readdir($handle)) !== false) { 
  5.  
  6. if (is_file($path . $file) && strstr($file, 'class') && !strstr($file, 'ClassLoader')) {
  7. $this->readed_dir[str_replace('.class.php', '', $file)] = $path . $file;
  8. }else if (is_dir($path . $file) && $file != '.' && $file != '..' && $file != '.svn') {
  9. $this->readDir($path . $file . DIRECTORY_SEPARATOR);
  10. }//end if
  11. }//end while
  12. closedir($handle);
  13. }//end if
  14. }
  15. ?>


Nie wiem czy dobrze robie pisząc w tym temacie, zgłaszając taki błąd!!!.

Ten post edytował kaniagandzowski 27.08.2007, 18:07:54
Go to the top of the page
+Quote Post
Sagnitor
post 5.07.2011, 12:53:10
Post #182





Grupa: Zarejestrowani
Postów: 34
Pomógł: 3
Dołączył: 29.05.2011

Ostrzeżenie: (0%)
-----


Być może uznacie mnie za archeologa, ale temat był wg. mnie bardzo ciekawy, a przez 4 lata od ostatniego postu mogło się wiele rzeczy zmienić.
Czytając tą dyskusję doszedłem do dwóch wniosków.

Są dwie najbardziej 'wydajne' metody autoloadu plików w projekcie:
- mapper generujący tablicę ze skojarzonymi nazwami klas wraz z ich ścieżkami + autoloader bazujący na tych mapach,
- konwencja nazewnictwa PSR-0, polegająca na używaniu przestrzeni nazw w taki sposób, aby wskazywały na plik klasy.

Oba sposoby posiadają zalety i wady. Pierwszy wykorzystujący mapy jest bardziej elastyczny w stosunku do drugiego. Właściwie niezależnie jaką strukturę katalogów przyjmiemy, mapper przeskanuje nam ją i zwróci odpowiedni plik. Głównym problemem jest wielkość wczytywanej mapy, która niekoniecznie musi być wykorzystana w całości (jednak z każdym żądaniem musi być wczytana do zmiennej klasy). Sugestiami co do tego problemu jest rozbicie mapy na mniejsze 'podkategorie'.

Drugi sposób wydaje się bardziej wydajny w większy aplikacjach, gdzie ilość plików przekracza kilka setek. W tym przypadku, aby załadować klasę nie musimy wczytywać nic z zewnątrz co mogło by obciążyć aplikację. Posługujemy się tutaj przestrzenią nazw. Obiekt w swojej nazwie zawiera ściężke do pliku, w którym znajduje się klasa. Wymogiem jest tutaj odpowiednie nazewnictwo oraz zorganizowana struktura katalogów.

Od tamtej pory wiele rzeczy mogło się zmienić, dlatego zachęcam do dalszej dyskusji. Mnie głównie nurtuje rozwiązanie sposobu pierwszego, aby był on wydajny nawet przy większych systemach.

Pozdrawiam
Go to the top of the page
+Quote Post
by_ikar
post 5.07.2011, 13:29:25
Post #183





Grupa: Zarejestrowani
Postów: 1 798
Pomógł: 307
Dołączył: 13.05.2009
Skąd: Gubin/Wrocław

Ostrzeżenie: (0%)
-----


Cytat
Oba sposoby posiadają zalety i wady. Pierwszy wykorzystujący mapy jest bardziej elastyczny w stosunku do drugiego. Właściwie niezależnie jaką strukturę katalogów przyjmiemy, mapper przeskanuje nam ją i zwróci odpowiedni plik. Głównym problemem jest wielkość wczytywanej mapy, która niekoniecznie musi być wykorzystana w całości (jednak z każdym żądaniem musi być wczytana do zmiennej klasy). Sugestiami co do tego problemu jest rozbicie mapy na mniejsze 'podkategorie'.


Tak, tyle że w tym temacie, ktoś słusznie umieścił kod, przynajmniej moim zdaniem, żeby maper mapował jedynie pliki z odpowiednim zakończeniem, tj: *.class.php lub *.interface.php dzięki czemu pomijamy wiele plików które są ładowane już z poziomu samej biblioteki. U siebie coś takiego stosuje i serializowana tablica nie przekracza 10kb. A czy to jest dużo? Wątpię, ustawienia, czy i18n mają znacznie więcej. Większość bibliotek ma jakieś swoje loadery, lub też w jakiś swój sposób ładują inne klasy i te klasy są nie potrzebne nam w zasadzie bezpośrednio w mapie naszych klas, potrzebna nam jest klasa główna która pozostałe załaduje, jeżeli będzie taka potrzeba. I tak klasy które chcemy załadować poprzez loader dajemy z końcówką .class.php a tych których nie chcemy załadować dajemy bez tej końcówki, samo .php i nasza mapa plików znacznie się zmniejsza wink.gif
Go to the top of the page
+Quote Post
Sagnitor
post 5.07.2011, 13:39:31
Post #184





Grupa: Zarejestrowani
Postów: 34
Pomógł: 3
Dołączył: 29.05.2011

Ostrzeżenie: (0%)
-----


Nie zaznaczyłem tego w swojej wypowiedzi, ale właśnie taki Autoloader miałem na myśli (wykorzystujący filtry suffixów). Zastanawiam się jednak, gdzie jest granica wielkości takiego wygenerowanego pliku i od jakiego rozmiaru zaczyna to wpływać na wydajność.

Co do innych propozycji, chodzi mi po głowie wyznaczenie Loaderowi tzw. "Core", czyli klas 'niskopoziomowych' systemu, które są zawsze ładowane przy każdym żądaniu. Klasy 'Core' byłyby przeparsowane do bytecodu, co przyspieszało by działanie aplikacji. Nie wiem jak dokładnie działają takie systemy cache (APC, MemCache). I tak końcowo by był:

Sparsowany core + autoload klas z mapy.

Pozdrawiam
Go to the top of the page
+Quote Post
Crozin
post 5.07.2011, 13:51:01
Post #185





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Zacznijmy od tego, że w niewielkich projektach wydajność autoloadera nie ma znaczenia. Albo inaczej, jest bardzo mało prawdopodobne, aby to właśnie autoloader był przyczyną problemów z wydajnością.

W przypadku tych większych aplikacji standardem są akceleratory, które umożliwiają jednokrotne skompilowanie kodu do bytecodu i jego późniejsze wykorzystanie. Trzeba tutaj jednak zaznaczyć, że domyślnie większość (wszystkie?) akceleratory mimo wszystko każdorazowo sprawdzają czy aby przypadkiem źródło pliku się nie zmieniło. Operacje z wykorzystaniem dysku, nawet tak trywialne jak sprawdzenie daty modyfikacji pliku, są generalnie powolne co w przypadku gdy każdorazowo mamy do sprawdzenia setki plików może być problemem. Tutaj rozwiązania są dwa:
1. Wyłączyć takie sprawdzanie w konfiguracji akceleratora, np. dla APC będzie to dyrektywa apc.stat.
2. Stworzyć cache'a plików, tj. zebrać wszystkie pliki i wrzucić ich zawartość do jednego pliku. Dzięki temu ograniczymy się do pojedynczego sprawdzenia daty modyfikacji pliku.

Ten post edytował Crozin 5.07.2011, 13:51:18
Go to the top of the page
+Quote Post
by_ikar
post 5.07.2011, 14:38:53
Post #186





Grupa: Zarejestrowani
Postów: 1 798
Pomógł: 307
Dołączył: 13.05.2009
Skąd: Gubin/Wrocław

Ostrzeżenie: (0%)
-----


W tym temacie jeden z użytkowników zamieścił właśnie takiego loadera, który sprawdzał suffixy, ale co to za problem samemu napisać proste wyrażenie "/([\w]+).(class|interface).php$/is" przy każdym dodanym pliku do tablicy wstawić preg_match i wyrażenie które podałem i wszystko. Kluczami są nazwy klas, wartością jest ścieżka bezwzględna. U mnie loader pierwsze przeładowanie sam tworzy cache w miejscu w którym znajduje się plik loadera. Kolejnymi sprawdzaniami zajmuje się pasywne cache które najzwyczajniej ponownie mapuje podane katalogi i tworzy cache.

Wydaje mi się że jest to najbardziej optymalne rozwiązanie, bo prawdę mówiąc loadery z przestrzenią nazw, również przeszukują tablice którą wcześniej mu się poda. No chyba żeby zrobić to na sztywno, gdzie przestrzeń nazw jest identyczna jak struktura katalogów. Tyle że mi takie rozwiązanie wcale nie przypadło do gustu. jestem w wielu przypadkach uzależniony od tego jak sobie ktoś zaprojektuje tą przestrzeń i robi się niekiedy burdel w katalogach, wtedy trzeba ręcznie poprawiać, a wole kiedy loader wie gdzie ma szukać klas, jak nie znajdzie znaczy że nie ma i syfu jako takiego nie ma. Oczywiście każdy ma inne przyzwyczajenia i upodobania.
Go to the top of the page
+Quote Post
Sagnitor
post 6.07.2011, 10:52:46
Post #187





Grupa: Zarejestrowani
Postów: 34
Pomógł: 3
Dołączył: 29.05.2011

Ostrzeżenie: (0%)
-----


@Crozin

Twój sposób numer dwa byłby bardzo dobry (sam tak kombinowałem), lecz jeszcze zanim wprowadzono namespace'y. Teraz próbując robić taki 'cache' (sklejke klas), jeżeli w pliku klasy jest oznaczona przestrzeń, a w kolejnej klasie tej przestrzeni nie ma to dojdzie do przypisania tej klasy do tego namespace'a. Zresztą opisywał już to Zyx w swoim wpisie o autoloaderze.

Zastanawiam się jednak czy jest narzędzie, które jest zdolne przetłumaczyć pliki PHP na bytecode generując plik z tym bytecodem. Póki co najwydajniejszym rozwiązaniem pozostaje autoloader oparty o mapy.
Go to the top of the page
+Quote Post
Crozin
post 6.07.2011, 11:17:27
Post #188





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


@Sagnitor: Nie widzę większych problemów:
  1. <?php
  2.  
  3. namespace Project\NS1 {
  4. class NS1C1 { }
  5. class NS1C2 { }
  6. }
  7.  
  8. namespace Project\NS2 {
  9. use Project\NS1\NS1C1;
  10. use Project\NS1\NS1C2;
  11.  
  12. class NS2C1 { }
  13. class NS2C2 { }
  14. }
  15.  
  16. namespace {
  17. class GC1 { }
  18. class GC2 { }
  19. }
  20.  
  21. namespace Project\Test {
  22. use Project\NS1\NS1C1;
  23. use Project\NS1\NS1C2;
  24. use Project\NS2\NS2C1 as AbcNS2C1;
  25. use GC2;
  26.  
  27. class Test {
  28. public function __construct(NS1C1 $a, NS1C2 $b, AbcNS2C1 $c, GC2 $d) {
  29. var_dump($a, $b, $c, $d);
  30. }
  31. }
  32. }
  33.  
  34. namespace XYZ {
  35. use Project\Test\Test;
  36.  
  37. new Test(new \Project\NS1\NS1C1(), new \Project\NS1\NS1C2(), new \Project\NS2\NS2C1(), new \GC2());
  38. }
Taki mechanizm jest nawet wykorzystywany w Symfony2.

Cytat
Zastanawiam się jednak czy jest narzędzie, które jest zdolne przetłumaczyć pliki PHP na bytecode generując plik z tym bytecodem.
A w jakim celu chciałbyś ten bytecode zapisywać na dysku?
Go to the top of the page
+Quote Post
Sagnitor
post 6.07.2011, 11:26:29
Post #189





Grupa: Zarejestrowani
Postów: 34
Pomógł: 3
Dołączył: 29.05.2011

Ostrzeżenie: (0%)
-----


Problem jest kiedy niektórzy piszą w ten sposób:

  1. namespace Project\NS1;
  2.  
  3. class Foo
  4. {
  5.  
  6. }


W sumie do końca kwestii bytecode'u nie przemyślałem. Podsumowując najlepsze rozwiązanie: sklejka + APC wink.gif
Go to the top of the page
+Quote Post
Zyx
post 13.07.2011, 10:14:52
Post #190





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Sagnitor -> mapa nie wyklucza stosowania konwencji PSR-0. Konwencja określa tylko, jak rozmieszczać klasy w plikach nazwanych w określony sposób i nie mówi nic o tym, że musi to być tłumaczone dynamicznie. Natomiast co do wydajności:

* Głównym parametrem jest obsługiwany ruch, a dopiero później wielkość serwisu. Nawet stosunkowo mały projekt przy dużym ruchu może znacząco zyskać, jeśli zmienimy strategię ładowania klas.
* Jest zauważalna różnica w czasie między korzystaniem z mapy klas, a dynamicznym tłumaczeniem. W tym drugim przypadku nawet w niezbyt dużych projektach tłumaczenie nazw klas na ścieżki potrafi zająć nawet do 40% łącznego czasu wykonania. Przynajmniej ja miałem takie wyniki przy zabawach profilerem, i mówię tu o naprawdę kompaktowej implementacji ładowarki. Jeśli mamy do czynienia z takimi kobyłami, jak Zend_Loader, to aż strach je mierzyć smile.gif.
* Wielkość mapy ma znaczenie, jeśli w każdym żądaniu wczytujesz ją z pliku zapisanego na dysku. Możemy to wyeliminować, używając pamięci współdzielonej.
* Gdy mapa jest już wczytana do pamięci, zapisana jest w postaci tablicy z haszowaniem. Takie tablice charakteryzują się bardzo dobrym średnim czasem dostępu rzędu O(h), gdzie "h" to średnia głębokość pojedynczego kubełka. W praktyce h jest równe 1 lub nieznacznie tylko większe od jedynki.
* Mapa klas nie podlega zbyt częstym zmianom, a jeśli już, to przebudowujemy ją w całości na nasze wyraźne żądanie. Wtedy możemy zastosować w tablicy haszowanie perfekcyjne charakteryzujące się stałym czasem dostępu, niezależnym od wielkości tablicy. Teraz klas możemy mieć i milion; poza zajęciem kilkudziesięciu megabajtów RAM-u wydajność nie ulegnie zmianie.
* Skąd wziąć tablicę z haszowaniem perfekcyjnym w PHP? Ano np. z rozszerzenia chdb, które niedawno odkopałem w PECL-u.

Nawiasem mówiąc, sklejarkę plików o której wspominasz, zaimplementowałem kilka dni temu i jest już dostępna w repozytorium Open Power Autoloadera. Działa dobrze i po prostu zamienia zapis namespace XYZ; na namespace XYZ{ ... }, poprawnie radząc sobie również z plikami, które nie korzystają z przestrzeni nazw. Ale takie sklejanie ma nieco inny cel:

- w praktycznie każdej aplikacji możemy wyróżnić zbiór klas, który musimy zawsze załadować bez względu na to, co dane żądanie HTTP robi.
- dla takiego zbioru klas możemy w ogóle pominąć automatyczne ładowanie i wczytywać je ręcznie.
- jeśli korzystamy z APC, zapisywanie kodu bajtowego na dysku jest nam niepotrzebne, gdyż jest on trzymany w pamięci RAM.
- ALE: nawet jeśli mamy kod bajtowy zapisany już w RAM-ie, APC domyślnie wykonuje na każdym pliku operację stat, aby sprawdzić czy w międzyczasie plik nie uległ zmianom. Czyli jeśli mamy nasze klasy główne porozbijane na 100 plików, wciąż PHP wciąż wykonuje 100 operacji dyskowych mimo, iż ma już wszystko w pamięci. Jeśli skleimy je w jeden plik, zrobi się z tego jedna operacja.
- Oczywiście apc.stat pozwala to sprawdzanie wyłączyć, ale wtedy przy najmniejszej zmianie kodu (nawet głupiej poprawce szablonu HTML) będziemy musieli zrestartować serwer/PHP lub czekać, aż się cache zdezaktualizuje.
- Jeśli nie mamy APC, zysk ze sklejenia też jest i też wiąże się ze zmniejszeniem liczby operacji dyskowych (konkretniej otwieranie i zamykanie plików oraz wiążące się z tym przeszukiwanie ścieżek na dysku).


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post
wookieb
post 13.07.2011, 10:36:11
Post #191





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




A to nie wystarczy już http://pl2.php.net/manual/pl/function.apc-store.php do przechowywania takiej "mapy" ?


--------------------
Go to the top of the page
+Quote Post
Zyx
post 13.07.2011, 11:12:50
Post #192





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Jak najbardziej wystarczy, tylko trzeba pamiętać o paru bolączkach APC:

- pamięć APC nie jest współdzielona między procesami,
- w szczególności nie możemy ze skryptu konsolowego wysłać polecenia wyczyszczenia cache i załadowania nowej mapy,
- aby zrobić coś takiego, musimy zrestartować procesy FastCGI lub Apache'a, ew. dodać do autoloadera jakiś przełącznik, który przeładuje mapę "przy najbliższym żądaniu", co może jednak wygenerować efekt wyścigu szczurów przy dużym obciążeniu,
- APC nie posiada tablicy z perfekcyjnym haszowaniem.


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post
Hellz
post 13.07.2011, 18:01:10
Post #193





Grupa: Zarejestrowani
Postów: 17
Pomógł: 0
Dołączył: 1.01.2007

Ostrzeżenie: (0%)
-----


Dlaczego nie trzymać mapy autoloadera w memcached, bez problemu jest współdzielony przez wszystko na serwerze, ostatnio wykorzystywałem go nawet do pisania wielowątkowej aplikacji w PHP, jako warstwy komunikacji między procesami. Piekielnie wydajny, dobrze działa z PHP, widziałem nawet wirtualki, które go obsługują.

Przebudowanie mapy można zrzucić na na skrypt konsolowy odpalany w cronie np. co minutę, bądź w ogóle w momencie zmian na serwerze jako kolejne zadanie phinga.

Osobiście byłbym daleki od sklejania plików, przy odpowiedniej konfiguracji serwera najczęściej używane powinny być i tak trzymane w ramie.


--------------------
O mnie: Krzysztof Zalasa na LinkedIn
Go to the top of the page
+Quote Post
Zyx
post 14.07.2011, 18:47:00
Post #194





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Bo jest kilka razy wolniejszy od APC*, a sama mapa ma na tyle mały rozmiar, że każdy serwer spokojnie może ją trzymać we własnym RAM-ie. Ponadto zauważ, że jeśli każdy serwer może być aktualizowany niezależnie, to ja bym nie chciał nawet, by mapa klas była współdzielona, bowiem potencjalnie straszne rzeczy mogłyby się wtedy wydarzyć.

W ogóle dziwię się trochę, że tak dużo programistów próbuje robić w temacie systemów cache itd. jakieś wojny religijne na zasadzie "a to jest lepsze niż tamto". Bzdura. Każdy system, tak samo jak każdy algorytm ładowania klas ma swoje określone przeznaczenie. Jedne są optymalizowane pod jeden scenariusz, inne pod inny. Ważne jest, by znać właściwości i umieć to wszystko podobierać.

* - co nie powinno dziwić, jeśli weźmiemy pod uwagę, że bezpośredni odczyt z RAM-u zawsze będzie szybszy niż komunikacja przez warstwę sieciową systemu operacyjnego.

Ten post edytował Zyx 14.07.2011, 18:51:31


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post
Hellz
post 14.07.2011, 23:38:34
Post #195





Grupa: Zarejestrowani
Postów: 17
Pomógł: 0
Dołączył: 1.01.2007

Ostrzeżenie: (0%)
-----


Cytat
co nie powinno dziwić, jeśli weźmiemy pod uwagę, że bezpośredni odczyt z RAM-u zawsze będzie szybszy niż komunikacja przez warstwę sieciową systemu operacyjnego.

Jasna sprawa, możesz zrobić jeszcze jeden test dodając połączenie z memcache nie przez host i port, a za pomocą socketa? Myślę, że można jeszcze trochę pokręcić gałkami, po weekendzie postaram się znaleźć chwilę i powtórzyć twoje badanie z optymalizacją memcache, wydaje mi się, że różnica się zmniejszy do max 2/3 razy, co przy odpalaniu 1 raz na request usera robi się IMHO w zasadzie pomijalne (moja wersja jest taka, że cała mapa jest przechowywana pod jedym kluczem i na początku wczytywana przez aplikację, później wszystko odbywa się już w samym PHP).

Cytat
bowiem potencjalnie straszne rzeczy mogłyby się wtedy wydarzyć.

Cytat
- pamięć APC nie jest współdzielona między procesami,

Chyba wybór mniejszego zła. Jeżeli dobrze Cię rozumiem, APC ma swoją własną wersję np. dla każdej instancji Apache i w momencie wprowadzania zmian konieczny jest restart? Mając na serwerze np. Redmine na mod_passanger chciałbym mocno tego unikać.


--------------------
O mnie: Krzysztof Zalasa na LinkedIn
Go to the top of the page
+Quote Post
Zyx
post 16.07.2011, 12:20:44
Post #196





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Wykorzystanie gniazd uniksowych niewiele Ci da. Tracisz wtedy główną zaletę Memcached, a zyskujesz? W zasadzie nic, ponieważ zapytanie i odpowiedź wciąż musi przejść przez jądro systemu operacyjnego, gdzie są kilka razy kopiowane z jednego bufora do drugiego. Samo przełączanie się w tryb jądra również jest kosztowne. Żadne gniazda, żadne inne mechanizmy komunikacji międzyprocesowej nie są w stanie dorównać pamięci dzielonej.

Domyślnie w PHP każde żądanie traktowane jest jako zupełnie niezależny byt. Pojedynczy proces FastCGI lub moduł Apache'a może jednak przetwarzać wiele żądań jako osobne wątki. APC zezwala jedynie na wymianę informacji między tymi wątkami (kod bajtowy + dane), nie przekracza natomiast granicy procesu. Z tego powodu:
* W trybie modułu Apache'a dane są współdzielone jedynie między wątkami tego samego procesu Apache'a,
* W trybie FastCGI dane są współdzielone między wątkami tego samego procesu FastCGI.

Przy czym w FastCGI najczęściej uruchomionych jest równolegle kilka/kilkanaście procesów, które na dodatek mogą być co X żądań restartowane w celu eliminacji potencjalnych wycieków pamięci. APC nie pozwala ani na współdzielenie danych między tymi procesami (każdy proces jest odizolowany od drugiego), ani na manipulację nimi np. z poziomu skryptu konsolowego, ponieważ to jest jeszcze jeden proces. Podobnie, z tego co wiem, działa XCache. Z tego powodu jedynym 100%-pewnym sposobem wyczyszczenia cache jest tutaj restart Apache'a lub wszystkich procesów FastCGI.

Pamięć współdzielona to mechanizm pozwalający na zmapowanie pewnego fragmentu pamięci na przestrzeń adresową więcej niż jednego procesu. Oba te procesy widzą ten fragment jako "swój" i mają do niego pełne prawa odczytu oraz zapisu. Najczęściej współdzielony fragment reprezentuje się jako plik na dysku, który działa trochę jak pamięć wymiany - w momencie pierwszego użycia poszczególne jego bloki są importowane do pamięci i odpowiednio oznaczane. Gdy blok znajdzie się w pamięci, zasadniczo nie ma różnic wydajnościowych między dostępem do prywatnej pamięci procesu, a pamięcią współdzieloną. Wszystko wygląda fajnie, ale jest tutaj jeden problem, który tłumaczy dlaczego typowe akceleratory go nie wykorzystują: programista musi samodzielnie zaimplementować całe i w dodatku współbieżne zarządzanie takim obszarem pamięci, co nie jest zadaniem trywialnym. Jedynym znanym mi rozszerzeniem PHP, które wykorzystuje systemowy mechanizm pamięci dzielonej, jest wspomniany już chdb, który radzi sobie z powyższym problemem bardzo prosto: pamięć jest tylko do odczytu -> nie potrzeba żadnej synchronizacji -> nie trzeba implementować zarządzania taką pamięcią. Zawartość takiego cache można przebudować jedynie hurtem.

OK, ale chyba tyle na temat mechanizmów cache, ponieważ trochę zboczyliśmy z tematu. Mam nadzieję jednak, że rozwiałem tym wpisem wszelkie wątpliwości, dlaczego:
* nie powinno się stosować Memcached do obsługi map klas,
* dlaczego APC działa tak, jak działa.

Ten post edytował Zyx 16.07.2011, 12:21:44


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post

10 Stron V  « < 8 9 10
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.03.2024 - 06:17