IE and DOMReady bug

Most famous method to catch DOMReady event in IE6/7 is utilizing script defer attribute:
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
  if (this.readyState == "complete") {
    init(); // call the onload handler
/*@end @*/

I’m developing a performance measurement tool and took this code to record time to DOMReady. Testing on a real site I’ve discovered that many records come with zero time to DOMReady. Filtering the records by browser I’ve got that only IE’s records were zero.
This zero time means that the event fired right after it was defined. This means that in practice on IE we could run the code bound to DOMReady before actually DOM Tree is ready.
There are similar issues described here.

After investigation I could reproduce it and found out that one of third-party advertisements caused the bug. It was inside IFRAME and it had alot of Javascript that was doing document.write() plugging next Javascript etc.

How to fix it?
There could be different solutions:

  • if possible, move the code to the bottom of the page instead of using DOMReady event
  • move the code into window.onload (execution will be delayed)
  • use another implementation of DOMReady for IE, there is solution that utilizes “doScroll()” method in order to check whether the content is ready yet

Note that it might be not so easy to find this bug. Your Javascript application that starts in DOMReady will work perfectly with your browser on your development server, but on production it may fail because of advertisements enabled and in worse scenario you’ll get geo-targeted advertisements and the bug will appear only for several countries.

How to catch it?
Measure the time in Javascript and send alert if the code runs right after event binding:

var page_start = new Date().getTime();
function bootstrap()
  if (0 == (new Date().getTime() - page_start))
    new Image().src="/developer_alert.php"; // send alert

Automated Data:URI CSS Sprites

Recently I found another interesting service: DURIS (Data URI Sprites). This is an automated solution for building Data:URI CSS Sprites for background images.

Basically you provide a page URL, then the service loads all styles of the page (both internal and external), finds all background images and encodes them into base64 (for data:URI format). As output, it provides a tar.gz file with HTML file and CSS files with encoded images in textual format.

The HTML contains the original pages with built-in code that checks browser version and plugs the styles with encoded images. There are several version of the styles for different browsers:

  • MHTML – for IE version < 8 (only IE8 supports data:URI )
  • data:URI – for all the other browsers
  • original styles – for the case when Javascript is disabled and for IE7 under Vista (there is a bug related to security issue with cached MHTML background images)

The advantages are:

  • all background images will be loaded in one HTTP request
  • it’s possible to quickly rebuild CSS sprites after making changes

This is a new tool that’s in beta stage so I would not use it in production.
The tool written in Java and the authors are going to opensource it as soon as release-candidate is ready.
(via Habr article in Russian)

I remind that besides Data:URI Sprites we have classic Image Sprites that involve joining images into another big image (opposite to base64 supposed by Data:URI). There are number of tools exist for Image Sprites and most advanced that I know is SmartSprites.

The advantage of Image Sprites over Data:URI Sprites is that it’s supported by almost all browsers including very old versions. The disadvantage is that Image Sprites composition cannot be fully automated and every time should be controlled by web developer.

Website Speed Optimization and Waterfall Diagram

Waterfall diagram is useful to find out how browser spending time loading page components. There is a an opensource tool built for IE called AOL Pagetest. It has online version where we can check sites via connections in USA and we can define connection speed.

I’ve prepared a sample page:, let’s look how we can optimize it.

Waterfall diagram of loading this page using IE7 (clickable):

Continue reading

Stylesheet Composition

Browsers cannot start rendering till all Stylesheets loaded. Visitors see blank page (or previous page) during loading of CSS so it’s especially important to load these components faster.
If you have many Stylesheet components, then visitors will have to wait more because of HTTP requests overhead.
Let’s look what can be done to reduce time to render.
Continue reading

Caching HTTP Headers, Last-Modified and ETag

What if we cannot predict lifetime of page content? If we have a page with info that changes unpredictably we still can use browser cache to avoid unneeded traffic.
Using validation mechanism browser sends HTTP request with info about cache entry and server can respond that the content wasn’t changed.
There are two validation methods: one is based on Last-Modified and the other is based on Etag.
Continue reading

Using CSS Image Sprites

Even fast connections suffer from multiple HTTP request overhead because of network latency and HTTP request processing overhead.
MSIE7 opens no more than 2 connections per domain, Firefox3 – 4-6 connections, Google Chrome – 6 connections.
Let’s suppose that time to first byte is 70ms (typical response time of via 1.5 Mbps ADSL connection from Dulles)
If a page view involves loading of 20 images from the same domain, then total overhead in MSIE7 is 20/2*70ms = 700ms. The more images site contains, the more time visitor will have to wait.
Continue reading

Caching HTTP Headers, Cache-Control: max-age

Caching speeds up repeated page views and saves a lot of traffic by preventing downloading of unchanged content every page view.
We can use Cache-Control: max-age=… to inform browser that the component won’t be changed for defined period. This way we avoid unneeded further requests if browser already has the component in its cache and therefore primed-cache page views will be performed faster.
Modern browsers able to cache static files even without any cache control headers using some heuristic methods but they will do it more efficient if we define caching headers implicitly.
Continue reading

Optimized Version of Rails MySQL Session Store is Available

The Problem

Original ActiveRecord sessions store is slow. It is fine for some low traffic sites, but it is too slow to use it for something larger. First of all, it is slow because ActiveRecord itself is slow. It is powerful ORM framework, but it is obviously overkill for such a simple task as a sessions management.

There are other possible solutions like cookie session store (session size is limited, no sensible data in sessions), memcached (no persistence + harder to implement high-available solutions).

That is why SqlSession store was created. It works with mysql directly with database APIs and works much faster than original AR session store. But sometimes it is still slow too because:

  • it creates/updates session on each hit – every bot or occasional web serfer create session records in your database so you end up with thousands of thousands of useless records in your sessions table while 99% of hits do not require any session updates.
  • it uses 32-characters string as a key for sessions records – all RDBMS work with string keys MUCH slower than with integers, so it would be much better to use integers, but we have these long session IDs and all session stores use them as a table key.
  • it uses auto_increment primary key, which causes table-level locks in InnoDB for all MySQL versions prior to 5.1.21. These table-level locks with unnecessary inserts cause really weird problems for large sites.

The Solution

As a solution for mentioned problems FastSessions Rails plugin was born.

Continue reading