Profile

Cover photo
Vladimir Melnick
Lived in Кривой Рог
131 followers|17,663 views
AboutPostsPhotosVideos

Stream

Vladimir Melnick

Shared publicly  - 
 
 
Just say no to reimplementing the browser's parser in JavaScript.

Here we have a library from Mobify (https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/) that allows you to "capture" the HTML in the document before the browser parses it. You get a chance to manipulate the content to indicate which image assets should get loaded by the browser.

It's clear that there is a real problem in browsers today that the Mobify team is trying to solve: browsers do not understand which image assets are actually going to be needed for responsive pages, so they tend to try to download all of the assets, which is obviously wasteful and also harmful for performance.

But the solution provided here is actually much worse than just loading all the image assets. Here's what the capturing API does:

1. inject a plaintext tag very early in the document:
   // Prevent the browser from downloading website resources
   document.write('<plaintext style="display:none">');
The plaintext tag never closes so all HTML that comes after it is parsed as plain text. Essentially this is a way of turning off the browser's HTML parser (and lookahead parser!) from JavaScript.

2. load some external JavaScript libraries needed to perform the capturing operations and prioritize which resources should be loaded

3. once the capture code loads, parses, and executes, create a child HTMLDocument which is used to parse everything after the plaintext tag in a new document context

4. invoke a callback in the main application that manipulates the document to enable/disable certain DOM elements

5. once the child HTMLDocument manipulation is complete, replace the main document's contents with this modified child document's contents

6. now the browser finally gets a chance to render some content to the screen

On the one hand, this is really cool. You just implemented a smarter HTML parser that understands media queries in JavaScript. On the other hand, you just reimplemented part of the browser... in JavaScript.

Let's dig a little deeper into what this means from a page load performance perspective. How much delay have we introduced to rendering the page as a result of loading the document this way? If we assume a mobile network round trip of 250 milliseconds and that we are loading mobify from a CDN, that's 750ms (DNS, TCP, request/response) blocking time before the browser even receives the first byte of mobify. Then it has to parse and execute mobify which will be non-zero time on a mobile device (let''s say 100ms), then it has to parse the document's contents in the child document (let's say another 100ms), then it has to copy the modified document's contents back to the main document (let's say another 100ms). So far we're already up over 1 second.

But it's actually even worse than this. None of the mobify code can execute until the main HTML has been fully downloaded. If the HTML document is large-ish (say, 10s of kB compressed), we're looking at incurring multiple additional round trips due to TCP congestion window growth before we even begin executing the mobify code. Let's say we incur 2 window growth round trips, for an additional 500ms.

Once this is all done, the stylesheet after the plaintext tag can finally begin downloading. That'll incur another round trip or 2, maybe more if we have to grow the TCP congestion window while downloading it.

Once this is done, after 2+ seconds on a mobile network, the browser can finally start rendering some content to the screen. It's hard to look at this as a performance win.

By trying to re-implement part of the browser in JavaScript, we've eliminated the browser's ability to parse or render any real page content, serializing the real parser behind the download, parse, and execution of external mobify JavaScript resources. It's going to be really hard to make up for this by eliminating the download of images. Keep in mind that JavaScript and CSS are parser and renderer blocking, whereas image assets do not block the parser or the renderer. Downloading more parser blocking resources in exchange for fewer non-blocking resources is very unlikely to be a performance win.

I am glad that the Mobify team is trying to improve responsive image efficiency, but solutions like this really need to live in the browser. The browser has so much more insight into the state of the document via its lookahead downloader, its ability to parse and render HTML in a streaming fashion, etc. It also doesn't have to download its parser from a web server (obviously), so none of those network delays are incurred by the browser's parser.

When you discover a shortcoming in the way web browsers parse your pages, rather than trying to implement a smarter browser in JavaScript, instead work on making the browsers themselves smarter. Open bugs with the browser vendors (or submit patches!), explain the problems you are encountering, and help the browser developers to understand what they need to do to make your pages load more efficiently.

Just say no to reimplementing the browser in JavaScript.

Update: to demonstrate the performance cost of using this solution on a high-latency (e.g. mobile) connection, here are two example pages, one that includes a single image, and another that includes the same image but loads the Mobify capture framework first. This isn't a real responsive page; the point of this demo is to show how much delay is added to fetching any of the assets on your page when you use Mobify capture.

First, the simple page:
http://www.modspdy.com/nocapture_example.html

And now the same page loading Mobify capture first:
http://www.modspdy.com/capture_example.html

Now, webpagetest results for each, using Chrome desktop on a high latency network (250ms round trip):
Simple page (without Mobify capture):
http://www.webpagetest.org/result/130405_5N_THC/1/details/
the image asset starts downloading at 810ms.

And the page with Mobify Capture:
http://www.webpagetest.org/result/130405_RK_TFB/1/details/
the image asset starts downloading at 2.57 seconds.

So we see that there is a roughly 1.75 second latency penalty as a result of using Mobify capture for this network configuration.
16 comments on original post
1
Add a comment...

Vladimir Melnick

Shared publicly  - 
 
Недавно в статье о Переменных и константах в Ruby я упомянул о том, что из строки можно
1
Add a comment...
In his circles
294 people
Have him in circles
131 people
Ankur Shah's profile photo
Александр Корытников (Парапсихолог)'s profile photo
Felipe Forbeck's profile photo
Евгений Попов's profile photo
Dima Newmendizo's profile photo
Виталя Бочо's profile photo
Ksenja Krivko's profile photo
Mike Pakhomov's profile photo
Андрей Козлов's profile photo

Vladimir Melnick

Shared publicly  - 
 
 
All the world’s major religions, with their emphasis on love, compassion, patience, tolerance, and forgiveness can and do promote inner values. But the reality of the world today is that grounding ethics in religion is no longer adequate. This is why I am increasingly convinced that the time has come to find a way of thinking about spirituality and ethics beyond religion altogether.
466 comments on original post
1
Add a comment...

Vladimir Melnick

Shared publicly  - 
 
Зачем? Все мы знаем, что при установке gem'ов часто генерация документации занимает
1
Add a comment...

Vladimir Melnick

Shared publicly  - 
 
В Ruby переменные - это просто ссылки на объект в памяти. Присваивая переменной значение,
1
Add a comment...
People
In his circles
294 people
Have him in circles
131 people
Ankur Shah's profile photo
Александр Корытников (Парапсихолог)'s profile photo
Felipe Forbeck's profile photo
Евгений Попов's profile photo
Dima Newmendizo's profile photo
Виталя Бочо's profile photo
Ksenja Krivko's profile photo
Mike Pakhomov's profile photo
Андрей Козлов's profile photo
Places
Map of the places this user has livedMap of the places this user has livedMap of the places this user has lived
Previously
Кривой Рог
Story
Tagline
Ruby on Rails в сердце
Introduction
Солипсист. Вас всех нет!
Bragging rights
Я не на самом последнем месте во многих вещах... Этим можно гордится?
Basic Information
Gender
Male
Other names
Владимир, Володимир, Володимирко, Egotraumatic, RubyDev