Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Cache obiektów
Forum PHP.pl > Forum > Przedszkole
Nh2003
Witam,

Przymierzam się do optymalizacji części moich skryptów i jestem na etapie tworzenia systemu obsługi cache'u. Zapytania do bazy danych ładnie mi się zapisują ale myślę jeszcze zrobić cache obiektów dla rzadko zmieniających się danych (~15minut). Próbowałem wykorzystać serialize/unserialize i zapis do pliku jednak wydajnościowo mnie nie zachwyciło - czas potrzebny na utworzenie nowych obiektów wykorzystując dane z zapisanych danych z bazy w formie cache'u zajmowało ok 1/3 czasu potrzebnego na wczytanie danych z systemu plików.

Przez myśl przeszła mi myśl żeby serializować obiekty i zapisywać do bazy ale wtedy zadziała cache od bazy danych i skończy się na tym że obiekty będą wczytywane z dysku.

Niestety na serwerze nie mogę zainstalować żadnych dodatkowych modułów do apache/php (np. memcached) - muszę samemu napisać takie coś. Czy ktoś może coś poradzić, podpowiedzieć? Każda wskazówka mile widziana smile.gif
marcio
Wiec zapisuje je do sesji :] to tez dobre wyjsce jesli chodzi o cache obiektow.
Quantum
Zapisując do sesji nie zapiszesz ich globalnie, a tylko dla jednego użytkownika. Sesja działa na systemie plików więc nie przyniesie lepszych rezultatów. Najlepszym rozwiązaniem byłoby zapisanie w pamięci podręcznej, ale tylko memcached przychodzi mi na myśl, ew. inne serwery cache-u działające na takiej zasadzie.

pozdrawiam.
Nh2003
Z sesją można by było spróbować - może apache jakoś lepiej obsługuje pliki sesji. Co do zapisywania tylko dla jednego użytkownika - część obiektów jest unikatowa dla każdego usera, jakby się udało chociaż je zapisywać to już by było lepiej niż jest.
marcio
Cytat
część obiektów jest unikatowa dla każdego usera, jakby się udało chociaż je zapisywać to już by było lepiej niż jest.

Tez o tym mowie :]

A obiekty globalne ktore zmieniaja sie raz na ruski rok jak np Path'e mozna zapisac do pliku

Zreszta config tez snitch.gif
erix
Cytat
Próbowałem wykorzystać serialize/unserialize i zapis do pliku jednak wydajnościowo mnie nie zachwyciło - czas potrzebny na utworzenie nowych obiektów wykorzystując dane z zapisanych danych z bazy w formie cache'u zajmowało ok 1/3 czasu potrzebnego na wczytanie danych z systemu plików.

A serializowanie obiektów przez metody __wakeup i __sleep? winksmiley.jpg

Cytat
Przez myśl przeszła mi myśl żeby serializować obiekty i zapisywać do bazy ale wtedy zadziała cache od bazy danych i skończy się na tym że obiekty będą wczytywane z dysku.

I tak, i nie; poleganie na cache'u silnika bazodanowego nie jest za dobrym wyjściem.

Cytat
Wiec zapisuje je do sesji :] to tez dobre wyjsce jesli chodzi o cache obiektow.

= serializacja + zapis do pliku. Poza tym, jak już wspomniano, ogranicza użycie tylko dla jednego użytkownika.

Cytat
Najlepszym rozwiązaniem byłoby zapisanie w pamięci podręcznej, ale tylko memcached przychodzi mi na myśl, ew. inne serwery cache-u działające na takiej zasadzie.

Serialize i do pliku. Ale nie ma na to jednoznacznej recepty.

Jeśli masz akcelerator zainstalowany z interpreterem, możesz skorzystać z jego przestrzeni w RAM (SHM), ale to zależy.

Cytat
Z sesją można by było spróbować - może apache jakoś lepiej obsługuje pliki sesji.

A co ma Apache do plików sesji...? To jest sprawa wyłącznie PHP.

Cytat
A obiekty globalne ktore zmieniaja sie raz na ruski rok jak np Path'e mozna zapisac do pliku

Równie dobrze można cały dokument wygenerować i przez rewrite zapisać do pliku. tongue.gif

Zapraszam do przeczytania mojego artykułu nt. cache w PHP: http://eriz.pcinside.pl/weblog/cache-danyc...teoria-211.html

Jak tylko chłopaki z PHPConu się uwiną z montażem video, zarzucę linkiem do mojej prezentacji (czyt: drugiej części tego artykułu winksmiley.jpg).
Nh2003
Napisałem sobie krótki skrypt żeby porównać czasy tworzenia nowych obiektów z wczytywaniem obiektów z cache'u i albo źle coś robię albo coraz więcej wskazuje na to że cacheowanie obiektów w systemie plików raczej nie ma sensu jeżeli brać pod uwagę tylko czas wykonywania się skryptu.

Czasy dla tworzenia 100000 obiektów:
Total: 1.3736710548401
Srednia: 0.0000137367

Czasy dla wczytywania z cache'u:
Total: 16.090548992157
Srednia: 0.0001609055

  1. <?php
  2. class test {
  3. private $t1;
  4. private $t2;
  5. private $t3;
  6. private $t4;
  7. private $t5;
  8. public $t6;
  9. public $t7;
  10. public $t8;
  11. public $t9;
  12. public $t10;
  13. protected $t11;
  14. protected $t12;
  15. protected $t13;
  16. protected $t14;
  17. protected $t15;
  18. public function __construct() {
  19. }
  20. public function setVals() {
  21. $this->t1 = 1;
  22. $this->t2 = 2;
  23. $this->t3 = 3;
  24. $this->t4 = 4;
  25. $this->t5 = 5;
  26. $this->t6 = 6;
  27. $this->t7 = 7;
  28. $this->t8 = 8;
  29. $this->t9 = 9;
  30. $this->t11 = 10;
  31. $this->t11 = 11;
  32. $this->t12 = 12;
  33. $this->t13 = 13;
  34. $this->t14 = 14;
  35. $this->t15 = 15;
  36. }
  37. public function __sleep() {
  38. return array("t1","t2","t3","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15");
  39. }
  40. public function __wakeup () {
  41. $this->t1 = 10;
  42. }
  43. }
  44. $iIle = 100000;
  45. $iStart = microtime(true);
  46. for ($i=0; $i<$iIle; $i++) {
  47. $temp = new test();
  48. $temp->setVals();
  49. }
  50. $iEnd = microtime(true);
  51. echo "Total: ",$iEnd - $iStart,"<br/>Srednia: ".number_format(($iEnd-$iStart)/$iIle,10),'<br/><br/>';
  52.  
  53. $sSerialize = serialize($temp);
  54. file_put_contents('object.obj',$sSerialize);
  55.  
  56. $iStart = microtime(true);
  57. for ($i=0; $i<$iIle; $i++) {
  58. $sSerialize = file_get_contents('object.obj');
  59. $temp2 = unserialize($sSerialize);
  60. }
  61. $iEnd = microtime(true);
  62. echo "Total: ",$iEnd - $iStart,"<br/>Srednia: ".number_format(($iEnd-$iStart)/$iIle,10);
  63. ?>


Mam jednak taką cichą nadzieję że to jednak ja coś partacze biggrin.gif

Niestety, na serwerze, na którym będzie to uruchamiane, nie mam żadnych akceleratorów itp, goły apache z php i mysql bez takich dodatków.

// Edit:

Eksperymentowałem z zapisem zserializowanego obiektu do bazy (tabela memory) ale czasy odtwarzania obiektow na podstawie wynikow zapytan sa jeszcze dluzsze niz te z plikow.
erix
Przecież metoda __sleep powinna zwracać stringa...

Cytat
Eksperymentowałem z zapisem zserializowanego obiektu do bazy (tabela memory) ale czasy odtwarzania obiektow na podstawie wynikow zapytan sa jeszcze dluzsze niz te z plikow.

Baza danych jako cache, to zły pomysł. Nie masz żadnych pól dłuższych niż 255 znaków.
Nh2003
Cytat
Przecież metoda __sleep powinna zwracać stringa...

Manual pokazuje co innego:

http://php.net/manual/en/language.oop5.magic.php
  1. public function __sleep()
  2. {
  3. return array('server', 'username', 'password', 'db');
  4. }

Cytat
serialize() checks if your class has a function with the magic name __sleep. If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized.


Co do bazy danych to się domyślałem że zły pomysł ale 5 minut testów potwierdziło teorię. Co do długości - przez phpmyadmin niby utworzyło pole varchar(1500) ale na ile jest to prawda to nie wiem, nie sprawdzałem w konsoli ani nie sprawdzałem czy idzie wcisnąć powyżej 255 znaków.
erix
Cytat
Manual pokazuje co innego:

Racja, moje niedopatrzenie.

Cytat
(1500) ale na ile jest to prawda to nie wiem, nie sprawdzałem w konsoli ani nie sprawdzałem czy idzie wcisnąć powyżej 255 znaków.

Nie idzie. winksmiley.jpg Ograniczenie DBMS, z tego co pamiętam.

Poza tym, na co do cache baza danych...? Rozumiem, że w SQLite, ale w MySQL? Na co zestawiać połączenie, jeśli w optymistycznym przypadku (zakładając, że wszystkie dane potrzebne do wygenerowania strony znajdą się w cache) DB zostanie nie tknięta...? (connect-on-demand)
Nh2003
Eksperyment z bazą był tylko eksperymentem, sprawdzałem czy to ma sens - potwierdziło się że nie ma. Ale sam problem z cacheowaniem obiektów nadal pozostaje - seialize/unserialize nie dają dobrych efektów, wykorzystanie __sleep/__wakeup tez niewiele zmienia. Nadal cache obiektów jest wolniejszy niż ich utworzenie. Oczywiście patrząc tylko na same obiekty, jeżeli brać pod uwagę że niektóre obiekty są tworzone na podstawie rzadko zmieniających się zapytań to można by ominąć etap wczytywania wyników zapytań i tworzenia obiektów przeskakując od razu do wczytania obiektów. Wtedy Taki cache ma sens.

Podbije raz, może jeszcze ktoś coś poradzi na ten cache smile.gif
Crozin
Widzisz, bo cacheuje się tylko to co ma sens. Oczywistym jest, że cały proces odczytania obiektu z pliku cachea będzie wolniejszy od jego utworzenia, jeżeli utworzenie ogranicza się do: $this->abc = 'def'; W Twoim teście zamień ostatnią linijkę metody setVals():
  1. $this->t15 = 15;
  2. // Zamień na
  3. for ($i = 0; $i < 100000; $i++) { $abc = mt_rand(); }
  4. $this->t15 = 15;
Nagle wczytanie z cachea jest nieco szybsze? smile.gif

Jeżeli wczytanie zserializowanych obiektów jest wolniejsze od ich normalnego utworzenia to oznacza to tyle, że próbujesz zoptymalizować coś co optymalizacji nie wymaga (przynajmniej teraz).
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.