Přejít k navigační liště

Zdroják » Různé » Granularita kešování

Granularita kešování

Články Různé

Data, která se často čtou a jejichž získání trvá dlouho, se vyplatí uložit do nějaké rychlejší vyrovnávací paměti. To je jeden ze základních obratů zrychlování programu. Jaká data ale do keše uložit pohromadě?

Článek vyšel na blogu Jakuba Vrány, na Zdrojáku ho přetiskujeme s autorovým souhlasem.

Vysoká granularita

V keši budeme mít samostatné záznamy pro každou jednotlivou částečku, kterou chceme zpracovat:

  • Celkový počet článků.
  • Seznam ID článků podle zvoleného řazení.
  • Nadpis, URL, perex, datum vydání a ID autora každého článku.
  • Jméno a URL autora.
  • URL a rozměry perexového obrázku.
  • Seznam ID skupin, do kterých je článek zařazen.
  • Název a URL těchto skupin.
  • Celkový počet názorů každého článku.
  • Počet nových názorů každého článku.

To je spousta údajů, které musíme získávat samostatně, což bude zdržovat. Některé údaje jsou navíc závislé na dříve načtených datech, takže s jejich získáním musíme počkat, až tato data budeme mít.

Nízká granularita

Často se proto přistupuje ke snížení granularity. Uložíme:

  • Celkový počet článků.
  • Seznam ID článků podle zvoleného řazení.
  • Všechna potřebná data o každém článku, ať už strukturovaně nebo případně rovnou jako HTML kód.
  • Počet nových názorů bychom z toho asi vyjmuli, protože ten bude pro každého čtenáře jiný.

Problém tohoto přístupu spočívá v tom, že pokud se cokoliv změní (např. někdo přidá názor), tak musíme keš invalidovat, případně i kaskádově. Buď tedy musíme definovat složité invalidační závislosti nebo každému záznamu nastavit platnost a po uplynutí určité doby ho obnovit, ať už se změnil nebo ne. První přístup vede k větší komplexnosti aplikace a invalidaci velkých částí keše třeba i při malé změně. Druhý přístup způsobuje zobrazování zastaralých dat a zbytečné obnovování keše, i když se data nezměnila.

Kombinovaná granularita

Oba přístupy lze zkombinovat:

  • Když dojde k zneplatnění keše s nízkou granularitou, tak stále platná data získáme z keše s vysokou granularitou.

Zásadní nevýhoda tohoto přístupu spočívá v tom, že se spousta dat ukládá duplicitně.

Co si vybrat

Já jsem dříve často jako jedinou možnost zrychlení aplikace viděl snižování granularity – čím víc toho budeme ukládat a načítat pohromadě, tím to přece bude rychlejší! Náročnost invalidace keše a s tím spojená větší komplexnost aplikace ale může tuto snahu zcela zhatit. Navíc můžeme dospět k tomu, že data do keše budeme ukládat jen proto, abychom je vzápětí smazali a uložili znovu. Keš tedy paradoxně může celou aplikaci zpomalit.

Nyní se proto zásadně kloním ke kešování s vysokou granularitou. Aby mohlo dobře fungovat, je potřeba splnit tři podmínky:

  1. Data získávat pokud možno v atomických celcích. Vyhnout se tedy např. spojování tabulek. S tím pomáhá NotORM.
  2. Dotazy do keše dávkovat a provádět je ve velkých blocích. V příkladu tedy např. informace o autorovi, seznamu skupin, perexovém obrázku a počtu názorů získat během jediné komunikace s keší pro všechny tyto údaje ze všech zobrazených článků najednou. S tím pomáhá NotORM 2.
  3. Každý požadavek musí proběhnout v konstantním čase, i logaritmický čas (k vidění např. u stromových indexů) toto řešení diskvalifikuje. To splňuje např. Memcache nebo MEMORY tabulky v MySQL.

Ve výsledku získáme aplikaci, která je jednoduchá (neobsahuje žádné invalidační závislosti), bezchybná (nezobrazuje zastaralá data), šetrná ke zdrojům (data ukládá jen jednou) a přitom výkonnostně obvykle optimální.

Srovnání: Basecamp Next používá kombinovanou granularitu – stejná data ukládá do keše třeba čtyřikrát a např. při přidání komentáře musí všechny tyto čtyři kopie zahodit a sestavit a uložit je znovu.

Přijďte si o tomto tématu popovídat na školení Výkonnost webových aplikací.

Komentáře

Subscribe
Upozornit na
guest
31 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
5o

Fajn čánok, princíp NotORM sa mi veľmi páči. Mysliš, že keby bol NotORM postavený nad Zend_Db bol by pomaľší?

Jan Egert

Cokoli postavené nad Zend_Db (minimálně co se MySQL týče) bude výrazně pomalejší než přímé provádění dotazů z principu fungování Zend_Db – každý dotaz transformuje na statement … který okamžitě po provedení zruší – fakticky tedy 3 požadavky na SQL server na provedení 1 query + na statementy MySQL neaplikuje query cache … tedy extrémní případ mnoha složitějších SQL dotazů, které by za normálních okolností vyřídila query cache, může Zendu trvat třeba 1000x déle …

Milan Stoklasa

Uvádět tento článek na Twitteru větou ve smyslu „jak by ti idioti mohli zrychlit Basecamp Next čtyřikrát, kdyby si odě mě nechali poradit“, to už je fakt vrchol.

Přitom řada tvrzení v článku je špatně na tolika frontách! Ale napsal to pan Vrána a proto to je prostě tak!

MW

Opravdu jste chtěl použít slovo atrofovat (ubývat, zmenšovat)?

Milan Stoklasa

hoops.. nikolivěk. byl jsem rozčilen :)

Kocour v botach

A neni preci jen dulezitejsi co se tam pise, nez kdo to pise? A nebylo by tedy lepsi, i pro nas nezkusene, v diskuzi uvest, co je v clanku spatne, pripadne pokud je clanek spatne jako celek napsat jiny, lepsi, ktery by poslouzil jako oponentsk?. :-)

Milan Stoklasa

Tak přesně pan Vrána článek uvedl takto: „Jak by mohl být Basecamp Next ještě čtyřikrát rychlejší, než je.“

Přitom autoři Basecamp Next (37signals) nejsou žádní začátečníci, stojí za vývojem frameworku Ruby on Rails a nějaké zkušenosti očividně mají. Dle svých vlastních slov se v nové verzi zaměřili především na rychlost.

Položme si otázku – opravdu by nechali jen tak bez povšimnutí možnost čtyřnásobného zrychlení?

Pan Vrána je ale geniální a tak si vybral vhodnou cache bez benchmarku jen na základě dojmologie. Ovšem možná že to je dobře, protože jeho přístup k benchmarkům je více než originální – viz zde http://php.vrana.cz/notorm-2.php na konci.

Kocour v botach

Ale k samotnemu tematu clanku – tedy zda vubec a pripadne jak, pomoci jakych nastroju apod. pouzivat cache,k tomu nam tu nic nenapisete? Ja opravdu nectu ty clanky proto, abych vedel kdo z autoru je chytrejsi nez nekdo jiny, ale abych se naucil neco co neznam, abych se necemu priucil. Tak mi prosim odpuste, ze je mi jedno, jak bylo nazvane nejake tweetnuti (nebo jak se tomu dnes rika ), ale spis me zajima, jestli a v jakych pripadech jsou jeho zavery spravne, pripadne nespravne.

Milan Stoklasa

Podle mě – čím větší balík dat leží v cache, tím lépe. Ideálně celá stránka. Tedy pravý opak.

Tvrzení z článku v odstavci „Nízká granularita“ považuji za vyloženě nesmyslné.

Nástroje: memcache či obdoba + něco na asynchronní zpracování dlouhých akcí – např. Resque. To je asi tak dnešní minimum.

František Kučera

Ad „Pokud se data v keši prakticky nemění, bývá nízká granularita skutečně nejlepší.“

To přece záleží na tom, jak pracné je následné zpracování těch „nízko granulovaných dat“ a nelze to říct takhle obecně.

Např. když budeš ta data z databáze validovat, transformovat a třeba prohánět přes Markdown*, tak můj skromný odhad je ten, že následné zpracování trvá déle, než vytažení dat z databáze – tudíž, když už používat mezipaměť, tak na vyšší úrovni (těch zpracovaných/zkon­trolovaných výstupů, ne těch surových dat, která vylezla z DB).

*) ono někdy stačí použít nějaký ne zrovna efektivní šablonovací nástroj a bude to znát a bude mít smysl si ukládat jeho výstupy do mezipaměti – ani nemusíme nic transformovat nebo markdownovat.

František Kučera

Všiml jsem si toho až po odeslání (větu jsem si přečetl špatně ovlivněn tím, jak tu propaguješ vysokou granularitu).

Nicméně obsah mého sdělení zůstává stejný – ty píšeš:

„Nyní se proto zásadně kloním ke kešování s vysokou granularitou.“

a s tím právě nesouhlasím, resp. nemůžu říct, že bych se k tomu „zásadně klonil“. Vtip je v tom, že obecně rozhodnout tuto otázku nejde a záleží na tom, kolik dá práce vytažení dat z databáze a kolik páce dá jejich následné zpracování.

BTW: nemáš po ruce nějaký test/měření, který by srovnával 1) aplikaci, která přistupuje přímo k dobře nastavené databázi 2) s toutéž aplikací, která by si vysoce granulovaná data kopírovala z databáze do cache a sama si ošetřovala aktualizace cache (např. po přidání článku/komentáře)?

František Kučera

Jen u hodně jednoduchých aplikací to funguje tak, že by údaj ze sloupečku tabulky odpovídal 1:1 nějakému kousku výstupu a nesouvisel s ničím jiným. Spíš to bude tak, že čím víc zpracovaná data (tzn. dál od databáze a blíž uživateli), tím víc atributů bylo použito – tzn. výstup je nějakou agregací a poskládáním/přes­kládáním původních dat, ne jen vyplivnutí databázové tabulky na stránku formou HTML tabulky nebo třeba seznamu.

Ondřej Kučera

Pořád je to jen dojem vs. jiný dojem. Podloženo pouze silnými slovy.

Můj dojem zase je, že ve znalostním víceboji vás proti 37signals by vyhráli oni. Takže když o nich napíšete, že něco mají vymyšlené neefektivně, opravdu zpozorním. A taky nevěřím.

Ondřej Kučera

Dovoluji si podotknout, že 37signals mají všechno v Ruby a tam jsou anonymní funkce a operátor yield tak nějak od začátku :)

GEe

Řekněme, jen tak bokem, že kluci v ROR, jsou pašáci, takoví malí egoisti:

http://zdrojak.root.cz/clanky/aktualne-tak-nam-hackli-github/

Honza Marek

Nedává mi matematicky moc smysl, jak může mít kombinovaná granularita horší výsledky než vysoká. Sice se občas zahodí nějaká cache, ale taková, která při vysoké granularitě vůbec neexistovala. Vychází mi to tedy tak, že kombinovaná granularita kombinuje výhody obou, jen je paměťově náročnější.

Honza Marek

Myslím, že Basecamp netrpí tak častými změnami, aby se mu nevyplatilo cachovat. Já v něm často hledám informace, kde co kdo napsal, což jsou jen čtecí požadavky. Facebook na tom asi bude o dost hůř, tam pořád někdo něco komentuje nebo lajkuje.

Navíc pokud si v BC zacachují třeba výpis jednoho komentáře, tak už to asi nemusí invalidovat nikdy – jeho html se nemění. Nebo počet diskuzí v projektu asi neni taky tak stěžejní číslo, aby se to muselo invalidovat při každé změně.

GEe

Hezké dopoledne,

přijde mi, že od pragmatických záležitostí jste se v obhajobě toho či onoho názoru dostali do tak obecné a teoretické roviny, že se naprosto vytratilo to, co se článek snaží řešit.

Celé je to o tom, že když se řeší jakýkoliv projekt, vychází se z provozních požadavků daného řešení a terpve až jsou známé tyto požadavky, může se řešit otázka, jestli cache, a pokud ano, pak jaké řešení je to správné. Řešit, jestli se něco provede o 0.005s rychleji při návštěvnosti 1000 lidí denně (= 5s/den) je plýtvání časem. Naopak, pokud se jedná o zrychlení 0.02 při návštěvnosti 5000 lidí za hodinu (= 100s/hodina), pak už stojí za to o tom nejen přemýšlet.

Nejde o chyby autoru Ruby, ani není řečeno, že nějaké udělali, jde o návrh architektury s ohledem na výkonnost.

Pokud by článek obsahoval v úvodu počáteční přepoklady či podmínky a malý příklad, na kterém se ukazuje smysluplnost, tak by tyhle empty diskuze s null přínosem !isset.

Ivan

Každý požadavek musí proběhnout v konstantním čase, i logaritmický čas (k vidění např. u stromových indexů) toto řešení diskvalifikuje. To splňuje např. Memcache nebo MEMORY tabulky v MySQL.
Tohle nechapu vite vubec jaky zaklad ma ten logaritmus? Jsou to radove stovky. Hloubka indexu je v realu „konstantni“ a pohybuje se mezi 3-5.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.