Po pierwsze - po co to kiedy jest shmop
http://pl.php.net/manual/pl/ref.shmop.phpPo drugie - większe prawdopodobieństwo, że firma hostingowa zgodzi się zainstalować
oryginale rozszerzenie, które jest razem z php poprzez --enable-shmop, niż zajmie się
instalacją rozszerzeń "trzecich", w dodatku wymagających dziwnych, mało znanych zależności
typu :
- konieczność posiadania libevent
- konieczność posiadania serwera cache memcached
- wymagana opbsługa epol w jądrze - z małym ale jądra 2.4 tego nie mają - trzeba więc je patchować
Po trzecie - serwer memcached musi byc uruchomiony w tle ( uruchomiona przez użytkownika )
więc wypada mieć shella - wyjątek stanowi, praca jako użytkownik nobody , uruchomiona przez admina.
Po czwarte, brak możliwości hashowania nazwy klucza pod jakim ma być zapisany nasz cachowany obiekt,
skutkuje to tym, że każdy będzie mogł odczytać zawartość cache, znając tekstowy klucz. Dodatkowo więc
wypadałoby napisać aggregato, który będzie zamieniał nam nasze klucze tworząc unikatowy hash.
Po piąte, łączenie się z serwerem cache, nawet po localhoscie jest wolniejsze niż odczyt z dysku metodą
unserialize(file_get_contents(....));
Po szóste, cache obiektów, zapytań SQL - w ogóle nie ma sensu z zasadniczych powodów
- obsługa FS w php i tak jest cacheowana (duża więc wydajność sama w sobie odczytu danych z dysku)
- podbnie zapytania SQL w bazach MySQL i podobnych równie jest cachowanaPo siódme, wyniki mówią same za siebie :
Testowi poddałem 32kB plik tekstowy zawierający tekst Lorem Ipsum (48 linii), plik należało pobrać do tablicy
i poddać procesowi cachowania.
Na ogień poszły 3 metody
1) Na dysku twardym poprzez unserialize(file_get_contents())
2) Używając rozszerzenia SHMOP z wykorzystaniem klasy Class5.Mnemonic
3) Używając rozszerzenia MemCache
Test 2 i 3 wykonano dwoma sposobami - 1 sposób to jednokrotna inicjacja obiektu, 2 sposób wielokrotna inicjacja obiektu
Jak przechowano dane : <?php
require_once('../libs/class5.mnemonic.php');
$lorem_ipsum = file('lorem.txt');
// Cache Mnemonic
$cache = new Mnemonic();
$cache -> store('lorem', $lorem_ipsum);
$memcache = new MemCache();
$memcache -> connect('localhost', 11211);
$memcache -> set('lorem', $lorem_ipsum, false);
// Cache Traditional
file_put_contents
('cache/lorem.cache', serialize($lorem_ipsum));
?>
Jak testowano : <?php
require_once('../libs/class5.mnemonic.php');
$passes = 3;
$iteration = 1000;
$cache = new Mnemonic();
for ($j = 0; $j < $passes; $j++)
{
for ($i = 0; $i < $iteration; $i++)
{
$wynik = $cache -> get('lorem');
}
}
echo 'Class5.Mnemonic (SHMOP Extension) #1 : '.((microtime(true)-$s)/$passes).'<br />';
for ($j = 0; $j < $passes; $j++)
{
for ($i = 0; $i < $iteration; $i++)
{
$cache = new Mnemonic();
$wynik = $cache -> get('lorem');
}
}
echo 'Class5.Mnemonic (SHMOP Extension) #2 : '.((microtime(true)-$s)/$passes).'<br />';
$memcache = new Memcache();
$memcache -> connect('localhost', 11211);
for ($j = 0; $j < $passes; $j++)
{
for ($i = 0; $i < $iteration; $i++)
{
$wynik = $memcache -> get('lorem');
}
}
$memcache -> close();
for ($j = 0; $j < $passes; $j++)
{
for ($i = 0; $i < $iteration; $i++)
{
$memcache = new Memcache();
$memcache -> connect('localhost', 11211);
$wynik = $memcache -> get('lorem');
$memcache -> close();
}
}
for ($j = 0; $j < $passes; $j++)
{
for ($i = 0; $i < $iteration; $i++)
{
}
}
echo 'file_get_contents Unserialize : '.((microtime(true)-$s)/$passes).'<br />';
?>
Wyniki : Cytat
Class5.Mnemonic (SHMOP Extension) #1 : 0.15039666493734
Class5.Mnemonic (SHMOP Extension) #2 : 0.12634968757629
Memcache #1 : 0.22323632240295
Memcache #2 : 0.55660033226013
file_get_contents Unserialize : 0.090231021245321
Jak widać Memcache wypadł najgorzej... można powiedzieć okropnie.
Jednak jest sens wykorzystania pamięci , ale nie w takim obrazie jak przedstawiono,
sens jest , gdy jednocześnie cacheujemy znaczne ilości danych, ale nie jakby się mogło
wydawać rozmiarowo ( kilka plików po kilkaset kB ), a setki/tysiące plików po kilkaset bajtów
lub parę kilobajtów. Jak wiadomo przewagą jest tu czas dostępu I/O ( czyli mam na myśli
tworzenie, kasowanie, odczytywanie, modyfikacja ). Dlatego sensem jest cachowanie
np. systemów szablonów, warstw danych, lub umieszczanie w pamięci shared memory
(memcached tego nie umożliwia), źródeł skryptów php.
Wtedy wyniki prezentują sie nieco odmiennie
Cytat
IO test on 5000 files
IO Result of Regular Directory : 1.1335179805756 seconds
IO Result of Class5.Mnemonic : 0.37275409698486 seconds
IO test on 10000 files
IO Result of Regular Directory : 2.5350189208984 seconds
IO Result of Shared Memory Directory : 0.91874718666077 seconds
Przykładem może być jak już wspomniałem umieszczenie w pamięci podręcznej
nie tyle co tylko szablonów TPL i kompilatów, ale także samych klas.
Cytat
Testing Chameleon 2.1.4 + Mnemonic => 359.57 requests/s
Testing OPT 1.1.0 => 160.29 requests/s
Testing Smarty 2.6.16 => 96.01 requests/s
i tradycynie z dyku ::
Cytat
Testing Chameleon 2.1.4 => 192.57 requests/s
Testing OPT 1.1.0 => 85.54 requests/s
Testing Smarty 2.6.16 => 56.01 requests/s
Na zakończenie parę uwag odnośnie artykułu :
1) extension=memcache.so a nie extension=memcache
d.so
2) nie napisałeś nic o instalacji serwera memcached oraz libevent
3) brak informacji o wymaganiu jadra 2.6 lub 2.4 z odpowiednia lata
To tyle
Pozdro.