Optimize and scale web widget performance

Serving widget content across hundreds of thousands of users per day is no easy task. A relatively small widget contains images, dynamic data, dynamic renderers, and manifest code that may consume 50 KB of space if you’re lucky. That’s 12 GB of bandwidth a day if you’re lucky enough to hit 250,000 gadget views hitting your servers, or about 3 file bundle requests per second. Even Google’s infrastructure has strained under the load of widget serving, but your sites don’t have to suffer the same fate.

In this post I’ll provide tips and tricks for widget developers interested in serving fast, reliable widget content to as many people as possible. I’ll highlight some of the best practices for serving web content and their specific application towards widget development. Your milage may vary. Please consult your operations professional before taking any magic pills.

  1. Browser and HTTP best practices still apply
  2. Reduce total network requests
  3. Reduce total request sources
  4. Speed of light still applies
  5. Cache
  6. Minify
  7. Draw frames
  8. Test
  9. Summary

Browser and HTTP best practices still apply

Your widget code relies on an integrated web browser and Internet connection to retrieve and display relevant content to your users. Placing your content within a smaller browser window or as a subsection of someone else’s does not change the fact that your code executes locally within a browser or its plugins and requests resources from one or more domains on the Internet.

Reduce total network requests

Scripts and CSS can be stored directly within your Google Gadget manifest file. Placing all your infrequently changing content in a single file reduces the amount of network connections created by your web browser and lets it focus on taking one big bite instead of multiple small bites.

Typical web development best practice is to separate CSS and JavaScript into separate files because the HTML content will change much more frequently than your styling and interaction code. Individual widgets are so tightly integrated it makes more sense to bundle the resources and serve it up as one package with each release. Developers may want to separate their resources during the development stage and execute a packaging script during the deploy stage.

Reduce total request sources

Retrieving a new piece of data requires both a file and a location. On the Internet we take a few relatively quick steps to help connect a series of letters and numbers to a unique position on a hard drive platter in a specific remote machine.

  1. I would like example.com/widget.xml please.
  2. A domain lookup occurs. Where is example.com located? How may I send laser beams closer to its location?
  3. Oh, you want the 2nd server on the 3rd rack on the 4th floor of this DataBank facility in Dallas. Sprint will take you there.
  4. Server software running on specialized hardware returns widget.xml to the requester.

If you don’t need to ask for the location of example.com you can skip a step and not perform what is called a DNS lookup. Each DNS record is stored by your local system(s) for a set period of time. Domains that distribute the load of user requests across multiple machines and appreciate quick fail-over ask domain servers to forget everything they just learned within minutes. Sites with a small set of servers that do not change location often might ask domain servers to update their location within hours or days.

Longer time between domain record updates shortens the steps needed to accurately serve your site’s content. You should evaluate your server configuration and IP pool to determine what frequency of updates best matches your Internet behavior.

Each sub-domain is treated as its own domain entry so the same rules apply. Your widgets.example.com site might be served from Boston by one provider while example.com is served in Dallas by another provider. Each new domain address adds some weight to your total page load.

Think globally, serve locally

The fastest server hardware and software is still limited by the laws of physics. Requests and their responses need to travel over twisted copper wires, fiber optics, and other modes of transport to connect a remote server and a local desktop. A customer in San Francisco receives data from Los Angeles faster than he will receive data from Atlanta. A fiber optic laser beam covers 400 miles quicker than it can cover 3000 miles, with typically less rest stops along the way.

Some companies work around this issue with content delivery network (CDN). A CDN optimizes each incoming request based on the requester’s location. Someone requesting your widget from Jacksonville might receive the file from servers in Atlanta while a user requesting the same data from San Diego might receive his file from Los Angeles. Akamai, Limelight Networks, and CacheFly are just a few of the delivery networks in the United States. Prices and performance vary but a CDN can help you conquer the speed of light.

Old vs. new

Web browsers load content into local memory and storage before displaying new content on your screen. Each time you load a widget and its resources the web browser will check for locally stored up-to-date copies of each file described on the page before downloading a new copy from your server. Like the milk in your fridge, each file should have an expiration label to help tools interacting with your content when it’s time to throw out the old stuff and get a new copy. If your widget references a file that has not expired from local storage your content loads a lot quicker than if it had to visit a remote server.

Minimized content

Adding spaces and new lines helps humans view source and author new content. While easy on the eyes, your formatting adds extra information to each file and takes up more space than necessary. The machine does not care about your CSS and JavaScript indentation habits and comments.

You should “minify” all content before publishing your widget. Tools such as JSMin and Dojo ShrinkSafe are two tools you can add to your publishing process to automatically process files for full minification.

Properly frame content

A web browser progressively loads a page on your screen to combine text, photos, sub-pages, and plugin content into a single browser window. You can help speed up the process by including extra properties in your widget code on any piece of content a browser might need revisit.

Images (img) and objects should have a defined height and width. This extra data lets browsers draw a box where the content will later be inserted instead of waiting for all your possible content to load before rendering the page.

Test your output

Tools such as the Firebug extension for Firefox and the WebKit Web Inspector help you profile your pages and discover coding errors. You can take a peek inside JavaScript loads created by your widget, view the total resources needed to assemble your widget content, and test your widget performance before releasing new content to the public.

Summary

I’ve outlined just a few of the ways you can optimize your widget code and scale up to more users. Your resources and use cases may vary, but it’s a good idea to at least be aware of various optimization options affecting all web content.

In my next post I’ll help you scale widgets using the Google Gadgets platform.