Jak mi IE připravil další z řady překvapení, aneb
Neříkej HOP...
Až do včerejška jsem si myslel, že záludnosti IE spočívají jen v prapodivných praktikách při interpretování kódu a CSS. Kdepak! Dokud vláda zasedá a Explorer běží, tak si nikdo nemůže být ničím jistý...
Už
jsem se zmiňoval o tom, že píšu malý webserver pro procesor 8051. Tenhle procesor běží na frekvenci nějakých 20 MHz a má 32kB paměti, takže je i laikovi jasné, že s tím neudělám žádné zázraky. Jenže ono je potřeba udělat alespoň malé kouzlíčko...
Ten webserver totiž má sloužit i ke stahování velkých bloků dat, tak okolo 20 MB. A to je kámen úrazu... Aby byla doba stahování alespoň trochu snesitelná, tak je potřeba, aby server posílal data rychlostí kolem 100kB/s. Jenže v takovém případě není, řečeno slovy mého bývalého šéfa, čas na hrdinství a vše je potřeba podřídit jedinému cíli: Rychlosti...
Podřídil jsem tedy vše rychlosti, optimalizoval jsem až téměř nečestným způsobem, vyhodil jsem vše, co nebylo stoprocentně nutné ke stahování, a ono to fungovalo. Rychlost byla až 120kB/s, jenže bohužel — v Mozille. I v Opeře, i ve Firefoxu, i v Konqueroru a v dalších. Jen ve
Zkoumákovi ani Ň. Což jsem, protože ho nepoužívám, zjistil až včera.
Spustil jsem tedy Ethereal, ponořil se do paketů a po několika hodinách zkoumání jsem objevil následující:
Mozilla (a další) stahuje soubory následujícím způsobem: Pošle HTTP požadavek HEAD a obdrží od serveru velikost, název a typ souboru. Dá uživateli na výběr co chce s dotyčným souborem udělat a až poté, co se uživatel vyjádří, pošle požadavek GET a stáhne soubor. Stahování vypadá pak asi takto:
OK, pošli blok dat od adresy 1000 — server pošle blok dat velikosti 1000 bajtů od adresy 1000
OK, pošli blok dat od adresy 2000 — server pošle blok dat od adresy 2000
OK, pošli blok dat od adresy 3000 — server pošle blok dat od adresy 3000
OK, pošli blok dat od adresy 4000 — server pošle blok dat od adresy 4000
OK, pošli blok dat od adresy 5000 — server pošle blok dat od adresy 5000
atd...
Idyla... Takhle mi to fungovalo naprosto bez problémů, takže takto jsem optimalizoval. A to jsem neměl!
Pak se do věci vložil IE. Jeho stahování vypadá takto: Pošle HTTP požadavek GET a server na to zareaguje tím, že pošle hlavičku a za ní hned data. IE dá uživateli na výběr co se souborem, ale mezitím mu server cpe další a další data a PC si je někam ukládá. Když se uživatel vyjádří, tak si IE uloží to co je zatím stažené a stahuje dál. (Je to vidět při stahování malých souborů — než člověk klikne na Uložit, tak už je soubor stažený.)
Jenže kámen úrazu je v tom, že ono místo, kam se ukládají ta data, je docela malé. Skoro by se dalo říct VELMI malé. Takže komunikace vypadala zhruba takto:
OK, pošli blok dat od adresy 21000 — server pošle blok dat velikosti 1000 bajtů od adresy 21000
OK, pošli blok dat od adresy 22000 — server pošle blok dat od adresy 22000
OK, pošli blok dat od adresy 23000 — server pošle blok dat od adresy 23000
OK, pošli blok dat od adresy 24000 — server pošle blok dat od adresy 24000
OK, pošli blok dat od adresy 25000 — server pošle blok dat od adresy 25000
v tuhle chvíli už je ale plné úložiště, a tak přichází požadavek:
OK, ale mně už se to tam nevejde, takže mi prosímtě pošli ještě jednou blok dat od adresy 25312
No a protože, jak jsem říkal, nebyl čas na hrdinství, tak server na ono OK reaguje tím, že posílá dál bloky dat od adres 26000, 27000, 28000... a PC odpovídá
OK, data dorazila, ale tyhle jsem nechtěl, pošli blok dat od adresy 25312 furt dokola, jak úřednice na berňáku.
Takže jsem dodělal kontrolu toho, jestli OK od Zkoumáka znamená „pošli další data” nebo „pošli data, co jsem už jednou dostal, protože je nemám kam dávat”. A v tu chvíli padla rychlost na 11 kB/s. A pokud má být učiněno protokolu zadost, tak už to lepší nebude...
Škoda. Taková pěkná optimalizace — a je v pdachu!
Ještě bych to mohl zaonačit tak, že bych tuhle kontrolu dělal jen v případě
User-Agent=Explorer. Tak by uživatel s Mozillou mohl stahovat sice ne-zcela-úplným protokolem, ale „na plnej kotel”, no a uživatel s IE by holt měl
protokolární smůlu... Jenže to by mi asi zákazník hodil na hlavu.
Dost možná je to záležitost nižší vrstvy systému než je ta v IE, bůh suď, faktem je, že se to s jiným prohlížečem nestává. Možná jde o buffer TCP protokolu, který je zaplněn proto, že si IE řekne o data a pak je nepřebírá, kdo ví...
Přitom by bývalo stačilo, kdyby IE posilal řádně HEAD a až po něm GET, tedy choval se podle hesla
nechtci data, dokud nevím co s nima! Pak by nemusel posílat své ZeroWindow pakety, vše by fungovalo k plné spokojenosti a svět by byl krásný, vlk by spal vedle beránka a vzduch by byl naplněn slovem MÍR! Ale to by byl svět až příliš jednoduchý.
Nezbývá než parafrázovat latinské
lex dura, sed lex —
Prohlížeč blbý, leč majoritní!
Smutné PS: Už se těším na komentáře, ve kterých mi budou nejrůznější odborníci a „odborníci” dokazovat, že blbej jsem já, protože můj server neimplementuje všechny možné požadavky TCP protokolu a já nefunkčnost svých „nečistých optimalizací” házím na IE. Pro všechny, co už už chtějí něco takového psát, tu mám stručné vysvětlení celého článku (už mě unavuje vždycky v komentářích vysvětlovat, že nadsázka je nadsázka, povzdech je povzdech, co je vážně, co ne a jak jsem to celé myslel, tak to udělám teď):
Ano, moje optimalizace na rychlost funguje všude s výjimkou IE, tak jsem ji odstranil, jede se dál rychlostí desetinovou a budu rád, když nějak zdvihnu rychlost na pětinu původní. Vím že IE v podstatě nedělá nic nestandardního a že posílá naprosto „běžný” požadavek, ale zarazilo mě to, protože žádný jiný prohlížeč, který jsem zkoušel, se takhle nechoval. A celý článek je míněn jako povzdech vývojáře nad tím, že aplikace je třeba testovat v IE nejen na úrovni zobrazování HTML a CSS, ale i na úrovni síťových paketů a požadavků, což jsem třeba já netušil, a zároveň by mohl sloužit jako ono „prošlapání slepé uličky”.
A pro naprosté pitomce: Jo, můžu si za to sám, titulek, podnadpis a vůbec celý článek je tendenční a strefovat se do MS je tak laciné!
Aktualizace Po dalších několika hodinách jsem objevil trik, kterým se IE nažral a rychlost je okolo 90kB/s! Juch!
Ale tenhle článek už mazat nebudu, nechám ho tu jako memento slepých cestiček... A pro Mormegila: Rychlost klesla při „předpisové” implementaci. Stačilo objevit ten drobný trik. Sice jsem tím úspěšně zaplácnul další cca 2kB paměti, ale účelu bylo dosaženo!