Cachowanie funkcji – przyspieszenie generowania stron
- Mateusz Żeromski | 2008-11-07 | Ciekawostki Optymalizacja Php
Kontynuując cykl optymalizacji aplikacji przedstawiam wam moja super klasę cachowania.
Przyspiesza ona generowanie stronek dość istotnie.
Wyobraźmy sobie system informatyczny, serwis www czy też inne ustrojstwo,
zawsze w każdej aplikacji jest chociażby jedna funkcja, która jest często
wywoływana i jej wykonanie zajmuje więcej czasu niż 0.05 sek, a jej wynik
zmienia się dość rzadko, np raz na godzinę. Czemu więc by nie wykonać
optymalizacji takiej funkcji? A co jeżeli bardziej się nie da? I tutaj
właśnie przedstawiam rozwiązanie :).
Po co?
Często mamy sytuację kiedy pewnych procesów nie da się zoptymalizować, np.:
proste zapytania do baz danych, odczytywanie plików, zewnętrznych zasobów itp.
Te procesy są uruchamiane często przez wiele osób, np 5 razy na minutę, 300 na godzinę,
a wynik tego procesu zmienia się nie częściej niż raz na godzinę.
Tutaj właśnie ma zastosowanie moja metoda cachowania :)
Na czym to polega
- Ładujemy cache.class.php
- Na początku funkcji którą chcemy cachować,
nadajem unikalny znacznik, np “MenuList”.
- Następnie sprawdzamy czy istnieje cache dla tego słowa kluczowego
- Jeżeli tak – to wyciągamy dane z cache i od razu zwracamy wynik.
- Jeżeli nie – funkcja się ładnie wykonuje po czym przed samym zwracaniem
wyniku do clasy Cache, są przesyłane dwie informacje: słowo klucz, wynik
- Funkcja zwraca wynik.
Ok to tak w skrócie i teorii, poniżej wklejam dwa kody źródłowe do analizy :)
index.php
Ten plik wywołuje funkcję getMenu(), która wykonuje się minimum 2 sek :),
więc ją przyśpieszmy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <? require 'cache.class.php'; function getMenu(){ $cacheName = 'MenuList'; if(Cache::is($cacheName)) return Cache::get($cacheName); sleep(2); $result = array('home', 'contact'); Cache::save($cacheName, $result); return $result; } function getmicrotime(){ list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); } $time_start = getmicrotime(); $menu = getMenu(); $time_end = getmicrotime(); $time = $time_end - $time_start; echo $time; ?> |
cache.class.php
Klasa odpowiedzialna za cachowanie, istnieją tutaj dwie zmienne
konfiguracyjne, pierwsza odpowiada za katalog gdzie ma być przechowywany cache
drugi mówi o ważności cacha.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <? define('CACHE_DIR', '/tmp/cache/'); define('CACHE_LIVE', 10); class Cache{ function is($name){ $r = false; $fileName = CACHE_DIR.MD5($name); if(is_file($fileName)){ if( (filemtime($fileName)+CACHE_LIVE) > time()) $r = true; } return $r; } function save($name, $content){ file_put_contents(CACHE_DIR.MD5($name), serialize($content)); } function get($name){ return unserialize(file_get_contents(CACHE_DIR.MD5($name))); } function clear($name){ unlink(CACHE_DIR.MD5($name)); } } |
Nie wykorzystana metoda to clear() – ją wykorzystuję w momentach kiedy inna
procedura ma wpływ na właśnie cachowaną, np.: jeżeli cachujemy funkcję getMenu,
która ma identyfikator “MenuList”, a w innej części aplikacji wykonujemy
aktualizację zasobów mających wpływ na wynik getMenu(), wywołujemy w niej
metodę Cache::clear(’MenuList’). Kolejne wywołanie getMenu() spowoduje wykonanie
cache na nowo :)
Podsumowanie
Powyższych kodów nie ma sensu abym opisywał – widać co one robią.
Pierwsze uruchomienie skryptu index.php powinno pokazać wynik
conajmniej dwie sekundy, następne mniej jak 0,0002 :).
Tutaj właśnie następuje to cachowanie. Można to zastosować do wszelkich procesów,
które są często uruchamiane i zawsze zwracają ten sam wynik, przynajmniej przez
jakiś określony czas.
Wykorzystuję ten prosty algorytm w wielu moich aplikacjach, serwisach itp. Gorąco polecam!
Tagi: Optymalizacja, php
1 mysql tabele tymczasowe at Mateusz Żeromski - Blog 2008-12-07 11:40:33
[...] Link do wspomnianego cache http://blog.zeromski.com.pl/2008/11/07/cachowanie-funkcji-przyspieszenie-generowania-stron/. [...]
2 A.Mazur 2009-08-31 01:20:14
A po cholerę MD5() nie wystarczy aby plik nazywałby się jak $name.
3 Mateusz Żeromski 2009-08-31 09:50:48
ano po to aby nie było ograniczenia w podawaniu nazwy cache – dzięki zaszyfrowaniu md5() możesz podać dowolną $name. Czasem może być że $name będzie się równało npo.: acasc/asc/asc/’;’sac[pasc, a jak wiadomo pliki lubią być nazywane alfanumerycznie. Dzięki md5 mam problem z głowy.