Technology

Performance issues: Rails Application Part-1(Frontend)

When we develop web applications like Ruby on Rails with rich web page designs, it means more scripts, stylesheets, images, and Flash in the page. Speed of application is inversely proportional to page load. More the page load, slower is the application. Front-end elements impart most of the page load. They increase the end-user response time. Most of this time is spent in downloading components like images, stylesheets, scripts, flash content, etc. These days to beautify pages more and more content elements are used. Number of such elements increase number of HTTP requests needed to render the page. We can apply client-side caching, but it would be useful only for repeated visitors and is of no use for the first time visitors. We can follow certain techniques to speed up web application, reducing page load, reducing HTTP requests, without compromising on rich frontend.

Manifesting files:

We can reduce the number HTTP requests made for fetching javascript and stylesheet files by combining them together into a single file i.e. manifesting. With some care taken while combining files will reduce challenges and resulting in improvement in response times.

Combining images:

Similar to JS and CSS files manifesting, we can combine images.

CSS Sprites:

We can combine CSS Background images into a single image and use it wherever required using CSS background-image and background-position properties to display the specific part of the image.

Image maps:

Mapping or combining multiple images into a single image. This is similar to CSS sprite, but it mainly consists of combining multiple images used for different components. It depends on defining coordinates of an image that can cause errors hence not recommended.

Stylesheets at the Top

Research on performance by Yahoo! discovered that moving stylesheets to the document HEAD makes pages appear to be loading faster. This is because putting stylesheets in the HEAD allows the page to render progressively. We always care about performance and want a page to load progressively that is; browser should display whatever content it has as soon as possible. Putting stylesheets near the bottom of the document prohibits progressive rendering in many browsers. These browsers block rendering to avoid having to redraw elements of the page if their styles change. The user is stuck viewing a blank white page.

Scripts at the Bottom

Scripts block parallel downloads. Browsers download no more than two components in parallel per hostname. If you serve your images from multiple hostnames, you can get more than two downloads to occur in parallel. While a script is downloading; however, the browser will not start any other downloads, even on different hostnames.

In some situations, it is not easy to move scripts to the bottom. If, for example, the script uses document.write to insert part of the page’s content, it cannot be moved lower in the page. There might also be scoping issues. In many cases, there are ways to workaround these situations.

Avoid CSS Expressions

The CSS expression accepts a function that decide which property to set. The CSS property is set to the result of evaluating the JavaScript expression.

As an example, the background color could be set to alternate every hour using CSS expressions:

 background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" );

This is not supported uniformly in all the browsers.

The main problem with expressions is that they are evaluated much frequently. They are not only evaluated when the page is rendered and resized, but also when the page is scrolled and even when the user moves the mouse over the page. Moving the mouse around the page can easily generate more than 10,000 evaluations of CSS expression. Thus, it makes page slower.

External JavaScript and CSS:

Prefer external CSS and javascript over inline because as mentioned in previous points they are cached by browsers. Inline reduces the number of HTTP requests that are needed, but increases the size of the HTML document. On the other hand, if the JavaScript and CSS are in external files cached by the browser, the size of the HTML document is reduced without increasing the number of HTTP requests.

Minify JavaScript and CSS

When code is minified all comments are removed, as well as unneeded white space characters (space, newline, and tab). In the case of JavaScript, this improves response time performance because the size of the downloaded file is reduced. CSS and JS are already compressed and minified during assets precompilation.

Remove Duplicate Scripts

Simply remove multiple same scripts rendered on pages. It generates multiple HTTP requests during page loading with some browsers.

Use GET for AJAX Requests

POST is implemented in the browsers as a two-step process: sending the headers first, then sending data. So it is best to use GET, which only takes one TCP packet to send (unless you have many cookies). The maximum URL length in IE is 2K, so if you send more than 2K data you might not be able to use GET.

An interesting side effect is that POST without  posting any data behaves like GET. GET is meant for retrieving information, so semantically we should use GET when you are only requesting data, as opposed to sending data to be stored server-side.

Post-load Components

Components that are not required while loading can be loaded after the HTML of the page is loaded. For example. Some javascript code that will work on some components when you click them. So this script is not required to be loaded first but can be loaded after the HTML content is loaded.

Preload Components

We can preload components by taking advantage of the time the browser is idle and request components (like images, styles and scripts) we will need in the future. This way when the user visits the next page, browser will have most of the components already in the cache and page will load much faster for the user.

There are three types with which we can achieve this:

Unconditional preload – as soon as onload fires, we can fetch      some extra components. Some image is requested onload. This image may not      be needed on this page, but it is needed on the pages user will      subsequently hit.
Conditional preload – based on a user action we can make a      guess what will be user’s next action and keep content preloaded in      advance.
Anticipated preload – preload in advance before launching a      redesign. Users are visiting the old site with full primed cache, so the      page is loaded faster. However, when the new design is launched, the user visit      with no entities cached. We can overcome this by preloading some      components of a new site before launching. The components will be loaded      with the old site and will be cached for next use when new site is launched.

Reduce the Number of DOM Elements

A complex page design means more data to download and means slower DOM access in Javascript as it will require to loop through  number of DOM elements.

A high number of DOM elements is a code smell that there is something wrong that can be improved with the markup of the page. There can be unnecessary DOM elements added like extra <div>s for some structure. Instead, we should find semantically correct way of doing this.

Minimize the Number of iframes

With Iframes, an HTML document is allowed to be inserted in the parent document. Understanding the working of iframe, it should be used only when it is effectively required.

iframe pros:

Helps with      slow third-party content like badges and ads
Good when      only part of HTML is to be rendered inside a page
Security      sandbox
Download      scripts in parallel

iframe cons:

Costly      even if blank
Blocks      page onload
Non-semantic
Issues      with search engine indexing

No ‘Not Found’

HTTP request getting ‘Not Found’ or 404 response is unnecessary slow down for user experience without any benefit. We need to make sure that all the scripts, stylesheets listed are available at the address specified.

Minimize DOM Access

Accessing DOM elements with JavaScript is slow so in order to have a more responsive page, we should Cache references to accessed elements. We should also update nodes “offline” and then add them to the tree. Moreover, we can avoid fixing layout with JavaScript.

Develop Smart Event Handlers

Pages feel less responsive because of too many event handlers attached to different elements of the DOM tree. We can use event delegation and event bubbling in combination to avoid this problem.

Choose <link> over @import

As we have seen that CSS should be at the top in order to allow for progressive rendering. However, in IE @import behaves differently than other browsers. It does not load the stylesheet at the time when it is encountered. Hence, it loads it as if it is at the bottom of the page. So performance wise it is better not to use it.

Image Optimization

GIFs should be used with correct palette size according to colors in the image.

Using PNG may save a lot. Also, we can use PNG optimizer tool like pngcrush on all the PNGs used.

We can use a tool like jpegtran on all your JPEGs to optimize and remove comments and other useless information losslessly from images.

CSS Sprites Optimization

We can arrange the images in the sprite horizontally instead of vertically. This, usually, results in a smaller file size. We can also combine similar colors in a sprite to keep the color count low.

While creating sprites, there should not be big gaps between images. This requires less memory for the user agent to decompress the image into a pixel map. For example 100×100 image is 10 thousand pixels, where 1000×1000 is 1 million pixels

Avoid Scaling Images in HTML

We should not use bigger images than required and adjust them by setting width and height in HTML. If requirement is of a small image then the actual image size should also be same.

Small and Cacheable favicon.ico

Browser will always request favicon.ico so make sure to set it because if it is not present then it will result in 404 Not Found which will be useless. Following are some considerations:

favicon.ico is small preferably under 1K.

Set Expires header for favicon.ico because when we want to change it we cannot rename it.

Components size under 25K

iPhone will not cache components bigger than 25K. Hence make sure to have component size under 25K so that it can be cached well.

Packing Components into a Multipart Document

Packing components into a multipart document helps to fetch several components with single HTTP request. Note: iPhone does not support.

Avoid Empty Image src

Image with empty string `src` attribute is not good. This can be directly from HTML or script. Even if the src is empty, browser will make HTTP request.

1 Comment

  1. Pingback: max

Leave a Comment

Your email address will not be published. Required fields are marked *

*