VÝKONNOST OPEN SOURCE APLIKACÍ

Rychlost, přesnost a trocha štěstí

Editoval Tavish Armstrong

Vydavatel:

CZ.NIC, z. s. p. o.

Milešovská 5, 130 00 Praha 3

Edice CZ.NIC

www.nic.cz

1. vydání, Praha 2016

Kniha vyšla jako 13. publikace v Edici CZ.NIC.

ISBN 978‒80‒88168‒12‒6

Přeloženo z anglického originálu knihy The Performance of Open Source Applications.

Toto autorské dílo podléhá licenci Creative Commons (creativecommons.org/licenses/by-nd/3.0/cz/), a to za předpokladu, že zůstane zachováno označení autora díla a prvního vydavatele díla, sdružení CZ.NIC, z. s. p. o. Dílo může být překládáno a následně šířeno v písemné či elektronické formě na území kteréhokoliv státu.

Editoval Tavish Armstrong

VÝKONNOST OPEN SOURCE APLIKACÍ

Rychlost, přesnost a trocha štěstí

Edice CZ.NIC

Předmluva vydavatele

Vážený čtenáři,

kniha, kterou právě držíte v ruce anebo čtete na svém mobilním zařízení, se zabývá v porovnání s dosavadními tituly Edice CZ.NIC poměrně specializovaným tématem – laděním výkonnosti softwarových aplikací.

Ačkoliv rychlost procesorů i kapacita paměti v posledním čtvrtstoletí rostly fenomenálním tempem, svižně běžící aplikace nejsou ani dnes ničím samozřejmým a bezpracným. Je to tím, že musí zpracovávat stále větší a složitější data a prezentovat výsledky stále náročnějším uživatelům. Vývojáři softwaru by proto měli výkonnostním aspektům věnovat pozornost jak při návrhu aplikací, tak i při jejich testování a ladění.

Kniha Výkonnost open source aplikací obsahuje dvanáct případových studií, jejichž autoři popisují řadu metod a triků vedoucích ke zlepšení výkonu. Škála je opravdu široká: počínaje spekulativními optimalizacemi, díky nimž nás moderní webové prohlížeče udivují svou předvídavostí, přes sofistikované algoritmy syntaktické analýzy, až po specifika mobilních zařízení. Pro ostříleného softwarového profesionála může být poměrně překvapivá předposlední kapitola, která demonstruje, že i „nepraktické“ funkcionální jazyky mohou nabízet elegantní řešení pro zvýšení výkonu. Sekundární, ale rovněž velmi zajímavou problematikou, které se tak či onak dotýká většina kapitol, jsou postupy, jimiž lze změřit reálnou výkonnost softwarových systémů a porovnat ji s alternativními implementacemi.

Přeji vám příjemné a inspirativní čtení.

Ladislav Lhotka, CZ.NIC

České Budějovice, 22. června 2016

Úvod
(Tavish Armstrong)

Úvod

Neustále se setkáváme s názorem, že počítačový hardware je v současné době tak rychlý, že si většina vývojářů nemusí dělat starosti s jeho výkonem. Douglas Crockford dokonce odmítl napsat kapitolu pro tuto knihu, a to z následujícího důvodu:

„Pokud bych měl přispět nějakou kapitolou do knihy, týkala by se anti výkonu: většina úsilí při honu za výkonem je vynaložena marně. Nemyslím si, že právě tohle hledáte.“

Donald Knuth k tomu poznamenal už před třiceti lety:

„Měli bychom zapomenout na nízkou výkonnost, řekněme v 97 % času: zdrojem všeho zla je totiž předčasná optimalizace.“[1]

Avšak u mobilních zařízení s omezeným výkonem a omezenou pamětí, stejně jako u projektů analýzy dat, které vyžadují zpracování terabajtů dat, potřebuje stále větší počet vývojářů zrychlit svůj kód, zmenšit datové struktury a zkrátit dobu odezvy. Zatímco stovky učebnic popisují principy operačních systémů, sítí, počítačové grafiky a databází, jen několik málo (pokud vůbec nějaké) vysvětlují, jak nacházet a opravovat chybné věci ve skutečných aplikacích, které jsou jednoduše zatraceně pomalé.

Tato sbírka případových studií je naší snahou zvětšit počet takových knih. Každou kapitolu napsali skuteční vývojáři, jejichž úkolem bylo zrychlit stávající systém, nebo přímo navrhnout něco rychlého. Pokrývají mnoho různých druhů softwaru a výkonnostních cílů. Mají společné detailní chápání toho, co se kdy děje, a jak se k sobě hodí různé části velkých aplikací. Doufáme, že vám tato kniha - stejně jako kniha The Architecture of Open Source Applications[2] - pomůže stát se lepším vývojářem, a to díky tomu, že vás necháme nahlížet těmto odborníkům přes rameno.

– Tavish Armstrong

[1]Poznámka vydavatele: Donald Knuth v roce 1974 napsal, že předčasná optimalizace je počátkem všech problémů.
Viz D.E. Knuth, „Structured Programming with go to Statements“, ACM Computing Surveys, vol. 6, pp. 261‒301, 1974

[2]Poznámka vydavatele: Kniha The Architecture of Open Source Applications je součástí série knih AOSA (www.aosabook.org).

Spolupracovníci

Tavish Armstrong (editor): Tavish studuje softwarové inženýrství na Concordia University a doufá, že na jaře roku 2014 absolvuje závěrečné zkoušky. Jeho domovská stránka je tavisharmstrong.com.

Michael Snoyman (Warp): Michael je vedoucím softwarovým inženýrem ve firmě FP Complete. Je zakladatelem a hlavním vývojářem webového frameworku Yesod, který poskytuje prostředky pro vytváření masivních, vysoce výkonných webových aplikací. Oficiálně studuje pojistnou matematiku a dříve pracoval ve Spojených státech v oblasti pojištění automobilů a domácností, kde analyzoval velké sady dat.

Kazu Yamamoto (Warp): Kazu je vedoucím výzkumníkem institutu IIJ Innovation Institute. Na open source softwaru pracuje již zhruba 20 let. Mezi jeho produkty patří Mew, KAME, Firemacs a Mighty.

Andreas Voellmy (Warp): Andreas je doktorandem informatiky na Yale University. Andreas při svém výzkumu softwarově definovaných sítí používá Haskell a publikoval open source Haskell balíčky, jako je například Nettle OpenFlow používaný k ovládání směrovačů pomocí Haskell programů. Andreas také přispívá do projektu GHC a udržuje jeho správce vstupu a výstupu.

Ilya Grigorik (Chrome): Ilya je inženýrem pro webový výkon, vývojář a zastánce týmu Make The Web Fast ve společnosti Google, kde tráví dny a noci zrychlováním webu a řízením adaptace best practices v oblasti výkonnosti. Ilyu najdete online na jeho blogu igvita.com a na Twitteru jako @igrigorik.

Evan Martin (Ninja): Evan pracuje devět let jako programátor ve společnosti Google. V životopisu má uvedené tituly z počítačových věd a lingvistiky. Pomáhal na mnoha malých projektech svobodného softwaru a na několika větších, včetně projektu LiveJournal. Jeho webová stránka má adresu neugierig.org.

Bryce Howard (výkonnost mobilních zařízení): Bryce je softwarový architekt, jenž je posedlý zrychlováním věcí. Pohybuje se v oboru více než 15 let a podílel se na řadě startupů, o kterých jste nikdy neslyšeli. Aktuálně se pokouší o psaní a je autorem úvodní knihy o webových službách Amazon pro společnost O’Reilly Associates.

Kyle Huey (Memshrink): Kyle pracuje ve společnosti Mozilla Corporation na zobrazovacím modulu Gecko, na němž je založen webový prohlížeč Firefox. Před přestěhováním se do San Francisca získal bakalářský titul na matematických studiích na University of Florida. Bloguje na adrese blog.kylehuey.com.

Clint Talbert (Talos): Clint se zabývá už téměř deset let projektem Mozilla, začínal nejprve jako dobrovolník a později se stal zaměstnancem. V současnosti vede tým pro automatizaci a nástroje a má povolení automatizovat cokoli, co automatizovat lze. Vyhlásil osobní vendetu všem nečinným cyklům procesoru u jakýchkoliv automatizačních strojů. Jeho dobrodružství ve světě open source a psaní můžete sledovat na adrese clinttalbert.com.

Joel Maher (Talos): Joel má více než 15 let zkušeností s automatizací softwaru. V posledních pěti letech se ve společnosti Mozilla zabýval automatizací a nástroji pro zdokonalování mobilních telefonů. Také převzal odpovědnost za Talos, aby rozšířil testování, zvýšil spolehlivost a vylepšil detekci regresí. V době, kdy běží jeho automatizace, chodí Joel rád ven a řeší nové výzvy v životě. Další informace o jeho dobrodružstvích na poli automatizace najdete na adrese elvis314.wordpress.com.

Audrey Tang (Ethercalc): Programátorka-samostudentka a překladatelka Audrey žijící na Tchaj-wanu v současnosti pracuje ve společnosti Socialtext na pozici „Stránka bez názvu“ a zároveň ve společnosti Apple v oblasti lokalizace a uvolňování inženýrství. Předtím Audrey navrhovala a vedla projekt Pugs, první fungující implementaci jazyka Perl 6, a pracovala v komisích pro design jazyků Haskell, Perl 5 a Perl 6, v jejichž rámci mnohokrát přispěla do repositářů CPAN a Hackage. Sledujte Audrey na jejím Twitteru @audreyt.

C. Titus Brown (Khmer): Titus se zabývá evolučním modelováním, fyzickou meteorologií, vývojovou biologií, genomikou a bioinformatikou. Nyní je docentem na Michigan State University, kde rozšířil své zájmy na několik nových oblastí, včetně reprodukovatelnosti a udržitelnosti vědeckého softwaru. Je také členem nadace Python Software Foundation a bloguje na adrese ivory.idyll.org.

Eric McDonald (Khmer): Eric McDonald je vývojářem vědeckého softwaru se zaměřením na vysoce výkonné výpočty (HPC), což je oblast, ve které pracoval po většinu času z uplynulých 13 let. Dříve pracoval s různými fyziky a nyní pomáhá bioinformatikům. Je držitelem bakalářského titulu v počítačové vědě, matematice a fyzice. Eric je už od poloviny devadesátých let fanouškem FOOF (svobodného a open source softwaru).

Douglas C. Schmidt (DaNCE): Dr. Douglas C. Schmidt je profesorem informatiky, místopředsedou programu informatiky a inženýrství a vedoucím výzkumníkem Institutu softwarově integrovaných systémů, to vše na Vanderbilt University. Doug publikoval 10 knih a více než 500 technických článků, které se týkají široké škály softwarových témat. Během posledních dvou desetiletí vedl vývoj ACE, TAO, CIAO a CoSMIC.

Aniruddha Gokhale (DaNCE): Dr. Aniruddha S. Gokhale je docentem na Katedře elektroinženýrství a informatiky a vedoucím vědeckým výzkumníkem v Institutu softwarově integrovaných systémů (ISIS), obojí na Vanderbilt University. Na svém kontě má více než 140 technických článků a jeho současný výzkum se soustředí na vývoj novátorských řešení výzev vznikajících v oblasti cloud computing a kyberneticko-fyzikálních systémů.

William R. Otte (DaNCE): Dr. William R. Otte je vědeckým výzkumníkem v Institutu softwarově integrovaných systémů (ISIS) na Vanderbilt University. Má takřka deset let zkušeností v oblasti vývoje open source middlewaru a modelovacích nástrojů pro distribuované systémy, systémy reálného času a vestavěné systémy, spolupracoval jak s vládními, tak průmyslovými partnery, mezi něž patří agentury DARPA, NASA a společnosti Northrup Grumman a Lockheed-Martin. Dosud publikoval množství technických článků a zpráv popisujících pokroky a podílel se na vývoji otevřených standardů pro middleware komponenty.

Manik Surtani (Infinispan): Manik je hlavním inženýrem pro výzkum a vývoj v JBoss, divizi middlewaru společnosti Red Hat. Je zakladatelem projektu Infinispan a architektem platformy JBoss Data Grid. Je také vedoucím pro specifikace JSR 347 (datové gridy pro platformu Java) a zastupuje společnost Red Hat ve skupině odborníků pro JSR 107 (dočasné kešování pro jazyk Java). Jeho zájmy se týkají cloudových a distribuovaných výpočtů, velkých dat a NoSQL, autonomních systémů a vysoce dostupných systémů.

Arseny Kapoulkine (Pugixml): Arseny strávil celou svou kariéru programováním grafických a nízko-úrovňových systémů v oblasti videoher, od malých úzce specializovaných titulů až po multiplatformní trháky nejvyšší třídy, jako je například FIFA Soccer. Miluje zrychlování pomalých věcí a další zrychlování rychlých věcí. Můžete ho kontaktovat na adrese mail@zeuxcg.org nebo na jeho Twitteru @zeuxcg.

Arjan Scherpenisse (Zotonic): Arjan je jedním z hlavních architektů frameworku Zotonic a zvládá pracovat na desítkách projektů naráz, obvykle s využitím frameworku Zotonic a jazyka Erlang. Arjan překlenuje mezeru mezi back-end a front-end projekty v Erlangu. Kromě problémů, jako jsou škálovatelnost a výkonnost, se Arjan často zabývá kreativními projekty. Navíc pravidelně přednáší na různých akcích.

Marc Worrell (Zotonic): Marc je respektovaným členem komunity jazyka Erlang a byl iniciátorem projektu Zotonic. Marc tráví svůj čas konzultacemi velkých projektů v Erlangu, vývojem projektu Zotonic a také je technickým ředitelem společnosti Maximonster, kde vytvořili MaxClass a LearnStone.

Poděkování

Tato kniha by nevznikla bez pomoci Amy Brown a Grega Wilsona, kteří mě požádali, abych knihu redigoval, a přesvědčili mě, že je to vůbec možné. Rád bych poděkoval také Tonymu Arklesovi za jeho pomoc v raných fázích redigování a našim technickým korektorům:

Colinu Morrisovi,

Coreymu Chiversovi,

Gregu Wilsonovi,

Julii Evans,

Kamalovi Marhubimu,

Kim Moir,

Laurie MacDougall Sookraj,

Loganu Smythovi,

Monice Dinculescu,

Nikitovi Pchelinovi,

Natalie Black,

Pierre-Antoinu Lafayetteovi.

Díky patří i malé armádě redaktorů a pomocníků, kterých bylo zapotřebí k tomu, aby tato kniha vyšla ještě v tomto desetiletí:

Adamu Fletcherovi,

Amy Brown,

Danielle Pham,

Eriku Habbingovi,

Jeffu Schwabovi,

Jessice McKellar,

Michaelu Bakerovi,

Natalie Black,

Alexandře Phillips,

Peteru Roodovi.

Amy Brown, Bruno Kinoshita a Danielle Pham si zasluhují zvláštní poděkování za pomoc při přípravě, grafickém zpracování a sazbě knihy.[3]

Redigování knihy je obtížný úkol, avšak je snazší, pokud máte přátele, kteří vás podporují. Natalie Black, Julia Evans a Kamal Marhubi byli po celou dobu trpěliví a zapálení.

[3]Poznámka vydavatele: Vztahuje se k originálu knihy The Performance of Open Source Applications.

Příspěvky

Na tvorbě této knihy tvrdě pracovaly desítky dobrovolníků, avšak stále toho ještě zbývá hodně udělat. Pokud chcete pomoci, můžete se zapojit hlášením chyb, překladem obsahu do jiných jazyků nebo popisem dalších open source systémů. Pokud se chcete zapojit, prosím obraťte se na nás na adrese aosa@aosabook.org.[4]

[4]Poznámka vydavatele: Vztahuje se k originálu knihy The Performance of Open Source Applications.

1 Vysoká síťová výkonnost prohlížeče Chrome
(Ilya Grigorik)

1 Vysoká síťová výkonnost prohlížeče Chrome

1.1 Historie a hlavní principy prohlížeče Google Chrome

Prohlížeč Google Chrome byl poprvé vydán v druhé polovině roku 2008 jako beta verze pro platformu Windows. Kód vytvořený společností Google, který prohlížeč Chrome pohání, byl také zpřístupněn s liberální licencí BSD - a je znám také jako projekt Chrome. Pro mnohé pozorovatele byl tento vývoj událostí překvapivý: máme čekat návrat tzv. válek prohlížečů? Bude prohlížeč Google opravdu o tolik lepší?

„Byl tak dobrý, že jsem byl v podstatě nucen změnit názor…“

– Eric Schmidt o svém počátečním odporu k nápadu začít vyvíjet prohlížeč Google Chrome.

Časem se ukázalo, že opravdu je. Dnes je Chrome jedním z nejrozšířenějších prohlížečů na webu (podle nástroje StatCounter má více než 35% podíl na trhu) a je nyní k dispozici pro Windows, Linux, OS X, Chrome OS a také pro platformy Android a iOS. Uživatelé si oblíbili jeho funkce a vlastnosti, a mnohé z inovací prohlížeče Chrome si našly cestu i do ostatních populárních prohlížečů.

Původní komiks o 38 stranách vysvětlující nápady a inovace prohlížeče Google Chrome přináší skvělý přehled procesu myšlení a navrhování, který se za populárním prohlížečem skrývá. To byl však teprve jen začátek. Klíčové principy, kterými byl vznik prohlížeče motivován, jsou i nadále hlavními principy jeho neustálého vylepšování.

Rychlost: Vytvořit ten nejrychlejší prohlížeč.

Bezpečnost: Poskytovat uživateli nejbezpečnější prostředí.

Stabilita: Poskytovat odolnou a stabilní platformu pro webové aplikace.

Jednoduchost: Vytvořit sofistikovanou technologii skrytou za snadno použitelným uživatelským rozhraním.

Jak tým zjistil, mnoho stránek, které v dnešní době používáme, nejsou jen webové stránky, jsou to aplikace. A stále ambicióznější aplikace vyžadují rychlost, bezpečnost a stabilitu. Každý z těchto požadavků by si zasloužil vlastní kapitolu, ale protože naším tématem je výkonnost, zaměříme se primárně na rychlost.

1.2 Mnoho aspektů výkonnosti

Moderní prohlížeč je, podobně jako operační systém, platformou a stejně tak je navržen i Google Chrome. Před prohlížečem Google Chrome byly všechny hlavní prohlížeče postaveny jako monolitické aplikace v rámci jediného procesu. Všechny otevřené stránky sdílely stejný adresní prostor a soupeřily o stejné zdroje. Chyba na kterékoliv stránce nebo v prohlížeči přinášela riziko pokažení celkového uživatelského dojmu.

Chrome používá model více procesů, který poskytuje každé záložce vlastní paměť, jakož i oddělený adresní prostor procesu a jeho bezpečnostní kontext. V dnešním světě vícejádrových procesorů se jasně ukazuje, že schopnost izolace na úrovni procesů a samostatné ochrany každé otevřené záložky od ostatních problémových stránek přinesla Chrome významný náskok před konkurencí. Je potřeba poznamenat, že ve skutečnosti většina ostatních prohlížečů se k těmto principům už také hlásí, anebo je v procesu migrace na podobnou architekturu.

Spuštění a běh webové aplikace v procesu prohlížeče primárně vyžaduje získání zdrojů, sestavení a zobrazení stránky, a vykonání JavaScriptu. Zobrazování a vykonávání skriptu se řídí jednovláknovým prokládaným modelem výpočtu – není možné provádět souběžné úpravy výsledného objektového modelu dokumentu (DOM). Zčásti je to způsobeno faktem, že pro JavaScript až do nedávna neexistovalo standardizované API pro práci s vlákny. Proto je optimalizace vzájemného prokládání vykreslování a vykonávání JavaScropti extrémně důležitá, a to jak pro webové vývojáře vytvářející aplikace, tak pro vývojáře pracující na prohlížeči.

Prohlížeč Chrome využívá k vykreslování stránek Blink, což je rychlé jádro prohlížeče vykreslující webové stránky, které je open source a splňuje všechny potřebné normy. Pro jazyk JavaScript používá prohlížeč Chrome svůj vlastní, velmi optimalizovaný runtime V8 JavaScriptu, který byl také vydán jako samostatný open source projekt a našel si cestu do mnoha dalších populárních projektů – např. do runtime systému Node.js. Optimalizace vykonávání JavaScriptu skriptovacím jádrem V8 anebo parsovacích a vykreslovacích procedur Blinku by ovšem byla málo platná, pokud by se prohlížeč zablokoval čekáním na uvolnění síťových zdrojů.

Schopnost prohlížeče optimalizovat pořadí a prioritu přístupu k jednotlivým URL (jednotná adresa zdroje v Internetu) je jedním z nejdůležitějších faktorů celkového dojmu uživatele. Možná si to neuvědomujete, ale síťová architektura prohlížeče Chrome je, a to v podstatě doslova, den ode dne chytřejší a pokouší se snižovat důsledky zpoždění každého zdroje: předpovídá pravděpodobné DNS dotazy (převod textových, doménových jmen zdrojů v Internetu na číselné IP adresy), zapamatovává si navštívenou topologii webu, předběžně se připojuje k serverům a dělá mnoho dalšího. Navenek se prezentuje jako jednoduchý mechanismus získávání zdrojů, ale uvnitř se jedná o propracovaný a fascinující příklad, jak optimalizovat výkonnost webu a maximálně uspokojit uživatele.

Pojďme tedy na to.

1.3 Jak vypadá moderní webová aplikace?

Než se dostaneme k zásadním podrobnostem toho, jak optimalizovat naši interakci se sítí, pomůže nám, pokud pochopíme trendy a kontext problému, před kterým stojíme. Jinými slovy, jak vypadá moderní webová stránka či aplikace?

Projekt HTTP Archive sleduje, jak se buduje web, a může nám při hledání odpovědi na tuto otázku pomoci. Namísto prohledání webu kvůli obsahu pravidelně prochází nejpopulárnější stránky a pro každou z nich zaznamenává a shromažďuje analýzy počtu použitých zdrojů, typy obsahu, hlavičky a další metadata. Statistiky k lednu 2013 vás možná překvapí. Průměrná stránka mezi 300 000 destinacemi na webu má následující charakteristiky:

• její velikost je 1 280 KB,

• skládá se z 88 zdrojů,

• připojuje se k více než 15 různým serverům.

Pojďme si to přepočítat. Zhruba 1 MB průměrné velikosti se skládá z 88 zdrojů, jako jsou obrázky, JavaScript a CSS, a tyto zdroje dodává 15 různých serverů, jak vlastních, tak i třetích stran. Navíc každé z těchto čísel v průběhu několika uplynulých let neustále narůstá a nic nenaznačuje tomu, že by se tento růst měl zastavit. Budujeme stále větší a ambicióznější webové aplikace.

Pokud na číselné údaje z HTTP Archive použijeme základní matematiku, zjistíme, že průměrný zdroj má velikost zhruba 15 KB (1280 KB/88 zdrojů), což znamená, že většina síťových přenosů je v prohlížeči krátká a nárazová. Tento samotný fakt přináší řadu komplikací, protože původní HTTP protokol navazoval jedno spojení pro jeden zdroj, což se časem stalo úzkým hrdlem datového přenosu, jak se webové stránky začaly skládat z čím dál tím většího množství zdrojů. Podívejme se tomuto tématu pod kůži a rozeberme si podrobně jeden z těchto síťových požadavků.

1.4 Životní cyklus požadavku na zdroje na síti

Specifikace časování navigace konsorcia W3C poskytuje prohlížeči aplikační rozhraní (API) a přístup k datům o časování a výkonnosti během životního cyklu každého požadavku v prohlížeči. Podívejme se podrobně na komponenty, z nichž každá přispívá důležitým dílem k dosažení optimálního dojmu uživatele:

Obrázek 1.1: Časování navigace

Po zadání URL webového zdroje začne prohlížeč tím, že zkontroluje svou lokální a aplikační vyrovnávací mezipaměť (keš). Pokud jste tento zdroj stáhli už dříve a máte k dispozici příslušné údaje o jeho platnosti (doba expirace, politiku uložení v mezipaměti prohlížeče, atd.), lze k vyřízení požadavku použít lokální kopii z mezipaměti. V opačném případě, pokud musíme opětovně ověřit, zda zdroj vypršel, anebo jsme ho jednoduše dosud neviděli, je nutné vyslat nákladný síťový požadavek.

Po zadání jména hostitele a cesty ke zdroji prohlížeč Chrome nejprve prověří stávající otevřená spojení, která může použít opětovně – sokety (programátorská abstrakce konce síťového spojení mezi dvěma počítači) se sdružují podle parametrů {schéma URL (protokol), server, komunikační port protokolu TCP/IP}. V případě, že jste nakonfigurovali proxy server (server mezi lokálním a vzdáleným počítačem, přes který prochází komunikace mezi nimi) nebo specifikovali skript automatické konfigurace proxy (PAC), prohlížeč Chrome zkontroluje připojení prostřednictvím příslušného proxy serveru. Skripty PAC umožňují použít různé proxy na základě adresy obsažené v URL nebo jinak specifikovaných pravidel, přičemž každý z nich může mít svou vlastní sadu soketů. Pokud není splněna ani jedna z výše uvedených podmínek, musí požadavek začít převedením doménového jména serveru na IP adresu protokolem DNS.

Pokud máme štěstí, záznam o převodu doménového jména na IP adresu je už uložen v mezipaměti DNS. V takovém případě je odezva obvykle dána jediným systémovým voláním. Pokud tam uložen není, pak je nutné před jakoukoli další činností vyslat DNS dotaz z lokálního počítače na DNS server. Čas, který zabere vyhledání v DNS, se může lišit podle vašeho poskytovatele internetového připojení, popularity stránky a pravděpodobnosti toho, zda bude jméno serveru nalezeno v DNS mezipaměti některého z postupně dotazovaných DNS serverů, stejně jako i podle doby odezvy autoritativních serverů dané domény. Jinými slovy, roli hraje velké množství proměnných, takže vyhledání DNS mnohdy zabere několik stovek milisekund. Ach jo.

Obrázek 1.2: Trojcestné navázaní spojení

Jakmile získá IP adresu, může prohlížeč Chrome otevřít nové spojení protokolem TCP/IP k cíli, což znamená, že musíme provést tzv. „trojcestné navázaní spojení“: pakety IP protokolu SYN, SYN-ACK a ACK v uvedeném pořadí. Tato výměna paketů zvýší každému nově vytvářenému TCP/IP spojení zpoždění o celou jednu obousměrnou cestu – bez možnosti využít jakoukoliv zkratku. Podle vzdálenosti mezi klientem a serverem a také podle vybrané cesty směrování můžeme nabrat desítky až stovky, občas dokonce i tisíce, milisekund zpoždění. A tato práce je vynaložena, která dobou svého trvání zvyšuje celkové zpoždění získání zdroje, ještě předtím, než se jediný bajt aplikačních dat rozběhne do sítě.

Pokud se připojujeme k zabezpečené destinaci (HTTPS), musí po navázání TCP/IP spojení dojít ještě k navázání spojení SSL - SSL šifruje a dešifruje data http protokolu, která v zašifrované podobě přenáší protokol TCP/IP. Tím se může přidat další latence v délce dvou obousměrných cest mezi klientem a serverem. Pokud je relace SSL uložena ve vyrovnávací paměti, můžeme z toho „vyváznout“ pouze s jednou dodatečnou obousměrnou cestou.

Konečně je prohlížeč Chrome schopen vyslat HTTP požadavek (requestStart na Obrázku 1.1). Jakmile je požadavek přijat, server jej může zpracovat a poté proudově zaslat data odezvy zpět do klienta. Tím je vyvolána minimálně jedna obousměrná cesta, plus doba zpracovávání na serveru. Poté máme konečně hotovo – pokud však není skutečná odezva přesměrováním na novou adresu požadovaného zdroje: v takovém případě musíme celý cyklus opakovat ještě jednou. Pokud máte na vašich stránkách nějaká bezdůvodná přesměrovávání, budete je teď zřejmě chtít přehodnotit.

Sčítali jste všechna ta zpoždění? Abychom si problém jasně znázornili, předpokládejme, že dojde k nejhoršímu možnému scénáři u typického širokopásmového připojení: v lokální DNS mezipaměti záznam nenajdeme, takže následuje síťový dotaz DNS protokolem (50 ms), navázání spojení TCP/IP, vyjednávání SSL a relativně rychlá doba odezvy serveru (100 ms) s obousměrným zpožděním (RTT – round trip time) 80 ms (průměrná obousměrná cesta napříč kontinentálními USA):

• 50 ms na DNS

• 80 ms na TCP/IP navázání spojení (jedno RTT)

• 160 ms na SSL navázání spojení (dvě RTT)

• 40 ms pro požadavek na server

• 100 ms pro zpracování na serveru

• 40 ms na odezvu ze serveru

Celkem 470 milisekund na jediný požadavek, což znamená, že 80 % zpoždění padá na režii síťového spojení a jenom 20 % tvoří skutečná doba zpracovávání požadavku na serveru – s tím musíme něco udělat. A to těch 470 milisekund může být ještě optimistický odhad:

• Pokud se odezva serveru nevejde do velikosti 4‒15 KB (tzv. congestion window protokolu TCP/IP), zvýší se komunikační zpoždění o jednu nebo dvě další obousměrné cesty.[5]

• Zpoždění způsobené SSL může být ještě větší, pokud potřebujeme získat chybějící certifikát nebo provést kontrolu stavu online certifikátu (OCSP), přičemž obojí bude vyžadovat úplně nové spojení TCP, které může přidat stovky nebo dokonce tisíce milisekund dalšího zpoždění.

1.5 Co znamená „dostatečně rychlý“?

Síťová režie DNS, navázání spojení a obousměrná zpoždění jsou v našem dřívějším příkladu hlavními faktory celkové doby – doba odezvy serveru má na svědomí pouze 20 % celkového zpoždění. Když to ale vezmeme kolem a kolem, mají tato zpoždění nějaký faktický význam? Pokud tuto knihu čtete, tak již pravděpodobně znáte odpověď: ano, mají, a velký.

Dosavadní výzkum dojmu uživatelů vytváří konzistentní obraz toho, jak jako uživatelé vnímáme délku odezvy jakékoli aplikace, ať už offline nebo online:

Zpoždění      

Reakce uživatele

0‒100 ms

Okamžik

100‒300 ms

Malé postřehnutelné zpoždění

300‒1000 ms 

Počítač pracuje

1 s a více

Přepnutí mentálního kontextu

10 s a více

Vrátím se později…

Tabulka 1.1: Vnímání latence uživatelem

Z tabulky 1.1 také jasně plyne, proč se komunita zabývající se webovou výkonností drží následujícího nepsaného pravidla: chcete-li udržet zájem uživatele, vykreslete své stránky, nebo alespoň poskytněte vizuální zpětnou vazbu za dobu kratší než 250 ms. V tomto případě se nejedná o samoúčelnou rychlost. Studie ve společnostech Google, Amazon, Microsoft i na tisícovkách dalších stránek prokázaly, že delší latence má přímý vliv na to, jak si bude vaše stránka stát: rychlejší stránky mají více zobrazení, větší zájem uživatelů a vyšší konverzní poměr.

Takže je to jasné: náš limit na zpoždění je 250 ms, a přitom, jak jsme viděli ve výše uvedeném příkladu, kombinace DNS vyhledávání, TCP/IP a SSL navázání spojení a doby přenosu zdroje přidá až 370 ms. Překračujeme limit o 50 %, a to jsme stále ještě nezapočítali dobu zpracovávání na serveru!

Zpoždění způsobená DNS, TCP/IP a SSL jsou ovšem mimo zorné pole většiny uživatelů a dokonce i vývojářů webu. Vznikají na takových úrovních sítě, na které sestoupila, nebo o kterých přemýšlí jen hrstka z nás. Přesto je každý z těchto kroků důležitým faktorem celkového dojmu uživatele, protože každý síťový požadavek navíc může přidávat desítky nebo stovky milisekund latence. To je důvod, proč je síťová architektura prohlížeče Chrome mnohem, mnohem více než pouze jednoduchý manipulační program pro sokety.

Teď, když jsme identifikovali problém, pojďme se podívat podrobněji na implementace.

1.6 Náhled na síťový stack prohlížeče Chrome

Architektura s více procesy

Prohlížeč Chrome používá architekturu s více procesy, což má velký vliv pro řešení každého síťového požadavku v rámci prohlížeče. Uvnitř prohlížeče Chrome se ve skutečnosti skrývá podpora čtyř různých modelů, které určují způsob, jakým se příslušný proces vytvoří.

Ve výchozím nastavení využívá prohlížeč Chrome na desktopech model jednoho procesu pro každou stránku. Tento model od sebe navzájem izoluje různé stránky, ale seskupuje všechny instance téže stránky do jednoho procesu. Pro jednoduchost ale předpokládejme, že máme pro každou otevřenou záložku samostatný proces. Z hlediska síťové výkonnosti nejsou rozdíly příliš podstatné, pro pochopení je ale model jednoho procesu na záložku mnohem snazší.

Obrázek 1.3: Architektura s více procesy

Architektura vyhrazuje každé záložce jeden vykreslovací proces. Ten obsahuje instance vykreslovacího jádra prohlížeče Blink a jádro V8 JavaScriptu, společně s vazebným kódem, který propojuje tyto a několik málo dalších komponent[6].

Každý z vykreslovacích procesů je vykonáván v odděleném procesu, který má omezený přístup k počítači uživatele – a to včetně sítě. Aby získal přístup k těmto prostředkům, komunikuje každý vykreslovací proces s hlavním procesem prohlížeče (zvaným kernel), který je schopen každému vykreslovači vnutit bezpečnostní a přístupová pravidla.

Meziprocesová komunikace a načítání zdrojů pro více procesů

Veškerá komunikace mezi vykreslovačem a procesem kernelu se v prohlížeči Chrome provádí prostřednictvím meziprocesové komunikace (IPC). Na systémech Linux a OS X se používá funkce socketpair(). Každá zpráva z vykreslovače se postupně předá se vyhrazenému vstupně-výstupnímu vláknu, které ho pošle procesu hlavního prohlížeče. Na příjmu poskytuje proces kernelu filtrační rozhraní, které umožňuje prohlížeči Chrome zachycovat požadavky IPC na zdroje (viz ResourceMessageFilter), které má řešit síťová architektura.

Obrázek 1.4: Meziprocesová komunikace

Jednou z výhod této architektury je, že všechny požadavky na zdroje jsou celkově řešeny ve V/V vláknech a jak UI generovaná činnost, tak síťové události spolu navzájem neinterferují. Filtrování prostředků probíhá na V/V vlákně v procesu prohlížeče, zachycuje zprávy požadavků na zdroje a přeposílá je do singletonu ResourceDispatcherHost3 v procesu prohlížeče.

Unikátní rozhraní umožňuje prohlížeči nejen řídit přístup každého vykreslovače k síti, ale také účinné a konzistentní sdílení zdrojů, jako například:

• Zásobník soketů a limity připojení: prohlížeč je schopen omezit počet otevřených soketů na profil (256), proxy (32) a objekty {schéma, server, port} (6). Všimněte si, že díky tomu je možné zřídit až šest připojení HTTP a šest připojení HTTPS ke stejným objektům {server, port}.

• Opětovné použití soketu: perzistentní spojení TCP/IP jsou zachována v zásobníku soketů ještě určitou dobu po obsloužení požadavku, což umožňuje opětovné použití připojení a ušetření režie pro nastavení DNS, TCP/IP a SSL (pokud je vyžadováno), jež je spojená s každým novým připojením.

• Pozdní vazba soketu: požadavky jsou asociovány s navázaým spojením TCP/IP pouze tehdy, je-li soket připraven vyslat požadavek aplikace. To umožňuje lepší prioritizaci požadavků (např. příchod požadavku s vyšší prioritou ve chvíli, kdy se soket připojoval), lepší průchodnost (např. opětovné použití ještě „teplého“ TCP/IP spojení v případech, kdy se stávající soket uvolní během otevírání nového spojení), i obecně použitelný mechanismus k předběžnému připojení TCP/IP a řadu dalších optimalizací.

• Konzistentní stav relace: autentizace, cookies a data uložená ve vyrovnávací mezipaměti jsou sdílena mezi všemi vykreslovacími procesy.

• Globální optimalizace prostředků a sítě: prohlížeč je schopen rozhodovat se s ohledem na všechny vykreslovací procesy a nevyřízené požadavky. Příkladem může být přiřazení síťové priority požadavkům vyvolaným záložkou v popředí.

• Prediktivní optimalizace: díky sledování veškerého provozu v síti je prohlížeč Chrome schopen budovat a zpřesňovat prediktivní modely za účelem zlepšení výkonnosti.

FCo se týká vykreslovacího procesu, tak jednoduše posílá požadavek s unikátním ID na zdroje do procesu prohlížeče přes IPC. Proces kernelu prohlížeče se pak postará o vše ostatní.

Načítaní zdrojů mezi platformami

Jedním z hlavních požadavků při implementaci síťového stacku prohlížeče Chrome byla přenositelnost mezi mnoha různými platformami: Linux, Windows, OS X, Chrome OS, Android a iOS. Síťová architektura je proto implementována z větší části formou jednovláknové (vyrovnávací mezipaměť a proxy mají vlastní vlákna) meziplatformní knihovny, která umožňuje prohlížeči Chrome opětovně využívat shodnou infrastrukturu a poskytovat stejné optimalizace výkonnosti. Tato architektura také poskytuje lepší možnosti pro optimalizaci napříč všemi platformami.

KomponentaPopis

net/androidVazby na runtime systému Android

net/baseBěžné síťové služby, jako je například vyhledání hostitele v DNS, cookies, detekce změny sítě a správa certifikátů SSL

net/cookiesImplementace ukládání, správy a načítání HTTP cookies

net/disk_cacheImplementace diskové a paměťové keše pro webové zdroje

net/dnsImplementace asynchronního DNS resolveru

net/httpImplementace protokolu HTTP

net/proxyKonfigurace proxy (SOCKS a HTTP), rozpoznávání, načítání skriptů atd.

net/socketPlatformě nezávislé implementace TCP soketů, SSL proudů a zásobníků soketů

net/spdyImplementace protokolu SPDY

net/url_requestImplementace URLRequest, URLRequestContext a URLRequestJob

net/websocketsImplementace protokolu WebSockets

Tabulka 1.2: Komponenty prohlížeče Chrome

Veškerý síťový kód je samozřejmě open source a naleznete jej v podadresáři src/net. Nebudeme probírat podrobně každou komponentu, uspořádání samotného kódu ale napovídá mnohé o jeho možnostech a struktuře. Několik příkladů je uvedeno v Tabulce 1.2.

Pro všechny zájemce představuje kód jednotlivých komponent skvělé počtení – je dobře zdokumentován a ke každé komponentě najdete spoustu unit testů.

Architektura a výkonnost na mobilních platformách

V současné době pozorujeme exponenciální nárůst používání mobilních prohlížečů. I podle skromných odhadů předčí už v blízké budoucnosti prohlížení na stolních počítačích. Pro tým prohlížeče Chrome jsou proto pochopitelně nejvyšší prioritou optimalizace zaměřené na uživatele mobilních zařízení . Na začátku roku 2012 byl spuštěn prohlížeč Chrome pro systém Android a o pár měsíců později jej následoval prohlížeč Chrome pro systém iOS.

První věc, které si na mobilní verzi prohlížeče Chrome všimnete, je, že se jednoduše nejedná o přímou adaptaci prohlížeče ze stolního počítače – ta by nebyla pro uživatele ideální. Už ze své přirozené povahy má mobilní prostředí jednak mnohem omezenější zdroje, a jednak zásadně odlišné provozní parametry:

• Uživatelé stolních počítačů je ovládají pomocí myši, mohou mít překrývající se okna, mají velkou obrazovku a většinou nejsou omezeni napájením. Obvykle mají také mnohem stabilnější připojení k síti a přístup k mnohem větším diskovým a paměťovým prostorům.

• Mobilní zařízení ovládají jejich uživatelé pomocí dotyků a gest, mají mnohem menší obrazovku, omezenou kapacitu baterií i příkon. Často též využívají dočasná připojení a mají omezené diskové a paměťové prostory.

Navíc neexistuje nic jako „typické mobilní zařízení“. Existuje široká škála zařízení s různými hardwarovými možnostmi, a pokud chce prohlížeč Chrome podávat ten nejlepší výkon, musí se přizpůsobit . Naštěstí přesně toto umožňují prohlížeči Chrome různé modely.

Na zařízeních se systémem Android využívá prohlížeč Chrome shodnou architekturu s více procesy jako verze pro stolní počítače – nachází se zde proces prohlížeče a jeden nebo více vykreslovacích procesů. Z důvodu paměťového omezení mobilních zařízení je jedinou odlišností to, že prohlížeč Chrome není schopen spouštět vyhrazený vykreslovací proces pro každou otevřenou záložku. Místo toho se na základě dostupné paměti a dalších omezení zařízení určí optimální počet vykreslovacích procesů, a ty se pak sdílejí mezi více záložkami.

V případech, kdy jsou k dispozici pouze minimální zdroje, nebo kdy nemůže prohlížeč Chrome spustit více procesů, může se přepnout na model zpracovávající více vláken v jednom procesu. Vlastně přesně takto se chová na zařízeních se systémem iOS – spouští jediný proces o více vláknech. Důvodem je odlišná politika izolace a spouštění procesů na této platformě.

A co síťová výkonnost? Zaprvé, prohlížeč Chrome používá u systémů Android a iOS síťovou architekturu shodnou se všemi ostatními verzemi. Tím jsou umožněny tytéž síťové optimalizace napříč všemi platformami, což dává prohlížeči Chrome značnou výhodu z hlediska výkonnosti. Některé faktory se ovšem liší a jsou často upravovány na základě možností zařízení a používané sítě. Příkladem může být třeba priorita spekulativních technik optimalizace, časový limit soketů a řídící logika, velikost vyrovnávací mezipaměti a další.

Například z důvodu šetření baterie může mobilní prohlížeč Chrome přistoupit k pomalému zavírání nevyužívaných soketů – sokety se zavřou jen při otevírání nových, aby se minimalizovalo využití rádiového přenosu. Stejně tak je povoleno předběžné vykreslování (viz níže), které vyžaduje značné síťové zdroje a výkon procesoru, pouze ve chvílích, kdy je uživatel připojen k Wi-Fi.

Optimalizace uživatelského dojmu mobilního prohlížení je pro vývojový tým prohlížeče Chrome jednou z položek s nejvyšší prioritou a můžeme očekávat, že v nadcházejících měsících a letech se dočkáme mnoha nových vylepšení. Ve skutečnosti by si toto téma zasloužilo vlastní samostatnou kapitolu – možná v dalším dílu ze série knih POSA.

Spekulativní optimalizace pomocí objektu Predictor prohlížeče Chrome

Prohlížeč Chrome se zrychluje tím, jak jej používáte. Toho je dosaženo za pomoci singletového objektu Predictor, který je vytvořen v rámci procesu kernelu prohlížeče. Prediktor sleduje typické způsoby využití sítě, učí se z nich, a předvídá pravděpodobné příští činnosti uživatele. Objekt Predictor zpracovává například tyto podněty:

• Zadávání textu do panelu Omnibox (URL) generuje vysoce pravděpodobné návrhy adres zdrojů, pro kterém může být zahájen DNS převod, předběžně navázáno TCP/IP spojení, nebo i případné vykreslení stránky na skryté záložce.

Technika

Popis

Předběžné rozpoznání DNS

Převádí doménová jména serverů předem, aby se redukovalo zpoždění DNS

Předběžné připojení TCP/IP

Předběžné načtení zdrojů

Předběžné vykreslení stránky

// požadavku.

};

Síťová architektura prohlížeče Chrome v kostce

1.7 Životní cyklus práce s prohlížečem

Optimalizace prvního startu

Optimalizace interakcí s panelem Omnibox

Optimalizace výkonnosti vyrovnávací paměti

Optimalizace DNS předběžným načtením

Optimalizace řízení spojení TCP/IP pomocí předběžného navázání

Optimalizace načítání zdrojů pomocí nápovědy pro předběžné načtení

Optimalizace načtení zdrojů pomocí předběžného obnovení prohlížeče

Optimalizace navigace pomocí předběžného vykreslování

1.8 Prohlížeč Chrome se zrychluje vaším používáním