WProf: Identify the bottleneck activities of your Web page


We designed a bunch of test pages to identify when one object in a Web page blocks another. This partially forms the basis of the dependency model that we used in WProf.

We load the test pages and observe the beginning and end timings of embedded objects with developer tools. We say that Object X blocks Object Y if loading Object Y starts after loading Object X completes. So timing is crucial here and we control (delay) the HTTP transaction time of an object when needed. Since many browsers have developer tools (e.g., Chrome, Firefox, IE, Safari), our methodology lets us identify dependencies across browsers. The limitation of the methodology is that we are unable to directly identify computation activities by tweaking network timings. Therefore we also look at browser source code and existing Web documentation.

Below, we show the results of the tests with links to the tests attached. We did experiments in Jan 2013 and thus we can't guarantee that same results hold forever.

Pairwise objects

We load a pair of objects in all combinations of CSS, image, html, JavaScript, and async JavaScript. The results below show whether the first object blocks the second one yes or not no.

The results suggest that loading JavaScript blocks loading iframes for all four browsers while loading CSS blocks loading iframes in IE. Combined with other sources of information, we find that loading JavaScript (and CSS in IE) blocks HTML parsing and we use this as a basis of our future experiments. Another finding is that async JavaScript works for Chrome and Firefox, not Safari 5 and IE 9.

#Chrome 22Firefox 18Safari 5IE 9
css, cssnononono
css, iframenononoyes
css, imagenononono
css, jsnononono
css, async jsnononono
iframe, cssnononono
iframe, iframenononono
iframe, imagenononono
iframe, jsnononono
iframe, async jsnononono
image, cssnononono
image, iframenononono
image, imagenononono
image, jsnononono
image, async jsnononono
js, cssnononono
js, iframeyesyesyesyes
js, imagenononono
js, jsnononono
js, async jsnononono
async js, cssnononono
async js, iframenonoyesyes
async js, imagenononono
async js, jsnononono
async js, async jsnononono

Embedded objects

In the pairwise tests, we don't consider the cases that embedded objects recursively embed other objects while those cases are common and can potentially introduce dependencies. Here, we add tests for embedded objects fetched from embedded objects.

First, we examine the kinds of objects that can embed objects. HTML and JavaScript can embed any kinds of objects and CSS can only embed images in the form of, for example, background-image. Images can't embed other objects. There are other kinds of objects such as Flash that can embed objects which don't work at the same layer and thus suggest little chance of introducing dependencies. Here, we focus on embedding objects from JavaScript and CSS. We don't include detailed results of embedding objects from HTML because embedded HTML objects are separated DOMs that embedded objects from them don't interfere with loading other objects. We confirmed this with tests.

1. Embedded CSS embeds another image

The image doesn't block parsing because we've previously known that image doesn't block parsing. Here, we focus on when the image is requested, for example, whether after the css is fetched yes or after the HTML tag that references the image is parsed no.

The finding is that image won't be requested until the HTML tag that references the image is parsed in all four browsers. This suggests that browsers are less aggressive in speculatively loading embedded images in CSS. Being more aggressive (loading images after the CSS that contains the images is fetched) can reduce page load latencies but risks the chance of loading images that are never used.

#Chrome 22Firefox 18Safari 5IE 9
css --> imagenononono

2. Embedded JavaScript embeds another object

We focus on whether embedded objects from embedded JavaScript block parsing (block iframes). We only consider embedding from sync JavaScript (no async and no defer) because it blocks HTML parsing. Besides the dimension of embedding different kinds of objects from embedded JavaScript, another dimension here is different ways of embedding. Since JavaScript can literally change anything in the DOM tree, we first consider two ways by modifying the DOM.

Adding a DOM node:

document.getElementById('XXX').innerHTML = "< img src='embedded_img.png' />";

Modifying a source attribute:

document.getElementById('img_id').src = "embedded_img.png";

Besides directly modifying the DOM tree, JavaScript can initiate AJAX requests to embed any kinds of objects. Example code below. Using async means that the rest of JavaScript can be executed after the AJAX request is made while otherwise it needs to wait until the response to the AJAX request is received.

var xhr = new XMLHttpRequest();
// xhr.open(HTTP method, URL, whether using async);
xhr.open("GET", "embedded_js.js", true);

We consider embedding image, CSS, and JavaScript in JavaScript using the above four ways. We follow the original JavaScript by an iframe to indicate whether parsing is blocked by the embedded objects.

The results suggests that embedding objects by adding a DOM node or modifying the source attribute doesn't block HTML parsing. However, browsers don't always support these ways. For example, IE doesn't support any of those and adding a < script > node is not supported by all four browsers. not fetched means that the embedded objects are not fetched while not allowed means that the browser explicitly says that this operation is not allowed. While sync AJAX request is supposed to block HTML parsing, it turns out that Safari 5 doesn't allow this.

#Chrome 22Firefox 18Safari 5IE 9
js --> image (add node)nonononot fetched
js --> image (add attr)nonononot fetched
js --> css (add node)nononot allowednot fetched
js --> css (add attr)nonononot fetched
js --> js (add node)not fetchednot fetchednot fetchednot fetched
js --> js (add attr)nonononot fetched
js --> * (async ajax)nonononot fetched
js --> * (sync ajax)yesyesnonot fetched


We previously said that our methodology is unable to uncover dependencies with computation activities. Here, we consider a limited case that we use our methodology to identify dependencies with computation activities---whether HTML parsing is resumed after loading JavaScript or evaluating JavaScript. We control the time to evaluate JavaScript by controlling the iterations of the loop (we need to ensure that it is not optimized by the compiler :p). We ensure that the JavaScript takes enough long time to be evaluated. If HTML parsing (observed from the requesting time of an embedded iframe) is resumed a long time after the JavaScript is received, we say that HTML parsing depends on evaluating JavaScript.

After doing this experiment on all four browsers, we find that HTML parsing depends on JavaScript evaluation for all four browsers, not only loading.

All combinations