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
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.
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: http://webscalingblog.com/waterfall/1/, let’s look how we can optimize it.
Waterfall diagram of loading this page using IE7 (clickable):
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.
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.
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 http://google.com 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.
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.
Compressing content on server before sending it over HTTP is a good practice since it saves a lot of traffic and makes transfers faster.
For example, Prototype.js is 123KB size and after Gzip compression it becomes only 28KB.
GZIP Compression also affects HTML so even primed cache requests that downloads mostly only HTML will be faster.
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.
As a solution for mentioned problems FastSessions Rails plugin was born.