Clientside Moment Profiling

When developing complex JavaScript applications, it is useful to profile the loading of your pages, so you can better understand the bottlenecks of performance. To the end user, the most important moment is when the browser indicates that the page is finished loading. As developers, it is our job to understand why loading takes so long and how to improve it. Todays article will introduce a simple widget called MomentTracker, which allows you to easily compile a collection of important client-side moments and then output them.

How to do it…

Include the following snippet as the first element in your head element:
var __momentTracker = {
	aMoments: [],

	addCookieHandler: function() {
		YAHOO.util.Event.on(window, unload, function() {
			var oneMinuteLater = new Date();
			oneMinuteLater.setTime((new Date()).getTime() + 60000);
			YAHOO.util.Cookie.set(__momentTracker, new Date(), {expires: oneMinuteLater});
		});
	},

	rollup: function() {
		var lastPageTime = YAHOO.util.Cookie.get(__momentTracker),
			aMoments = __momentTracker.aMoments,
			rs = [],
			i, t1, t2;

		if (lastPageTime) {
			__momentTracker.lastPage = new Date(lastPageTime);
			aMoments.unshift(lastPage);
		}

		for (i=aMoments.length-1; 0ms +  =  + aMoments[i] +  -  + aMoments[i-1]);
		}

		return rs;
	},

	trackMoment: function(sName) {
		__momentTracker[sName] = new Date();
		__momentTracker.aMoments.push(sName);
	}
};
__momentTracker.trackMoment(pageStart);

Then anytime you want to track an important moment, call the trackMoment function with the name you would like to call that moment:

To measure the time between pages, we need to setup a cookie (call this anytime after YAHOO.util.Cookie and YAHOO.util.Event are included):

__momentTracker.addCookieHandler();

And lastly, to output the results call:

Event.on(window, load, function() {
	__momentTracker.trackMoment(afterJavaScript);
	Y.log(__momentTracker.rollup().join("\n"));
});

How it works…

The trackMoment function simply stores a date object, at the moment it is executed. The addCookieHandler function adds an unload event to record when the user leaves the page. The rollup function iterates on all the moments, calculates the difference between them in milliseconds, and then returns the results.

The implementation in this article, uses the YUI Logger module to print the results. However, you could modify the rollup function to suit your needs, and use the results in a more meaningful way. At Mint.com we pass the tracked moments times to the server, where they are aggregated into our performance monitoring system.

Ive put together a quick demo page to show it working.

Using Data URIs

After reading Nicolas Zakas article, Data URIs make CSS sprites obsolete, I was inspired to see how easy it would be to put into practice. His CSSEmbed JAR uses Base64 encoding for data URIs and MHTML to be backwards compatible with IE 6 and 7. So the logical step was to create a build script that runs CSSEmbed against all my CSS files.

Getting ready

You will need to install a copy of ...

Simple JavaScript Function To Include CSS

This article explains how to write a simple JavaScript function to include CSS files and notify when the loading of the file is complete. The issue is that most browsers do not fire a load event when the link element finishes processing the included CSS rules. And while many libraries have mechanisms for notifying when the CSS is included, I believe this technique is lighter and more elegant. A special thanks goes out to the ...

Function Hijacking Pattern

Sometimes when working with JavaScript libraries and widgets, you may want to extend or augment the behavior of certain functions without breaking the existing functionality or completely extending the object. Todays article will explore the Function Hijacking Pattern, which can be used to augment a function with your own logic.

How to do it…

The following is a simple example using the hijack pattern to augment a function:
var obj = { // static ...

Defer Function Execution Until Variables Are Available

I recently wrote this simple function, which hijacks a function attached to an object, automatically deferring calls to it (in the order received), until an availability function returns true. I find this to be useful in large applications with many dependencies, especially third-party ones, where it can be difficult to know that the variables/functions used by a function exist. And rather than check for the variables and handle function deferment manually, the function in todays ...

Introducing Web Workers

The HTML 5 specification introduces a new technology called Web Workers, allowing developers to spawn new threads for processing JavaScript code. This is a major improvement from the current state of the web, as it allows JavaScript code to execute outside of the UI thread, so your application is still responsive during long-running scripts. However, due to the nature of Web Workers there are restrictions to what they can and cant do, and how to ...

Handle Slow Processes Without Blocking the UI

Note: This post was inspired by work done by Nicholas Zakas. It turns out he has already written a blog article solving this problem and has a more elegant solution at Timed Array Processing in JavaScript. Since JavaScript is executed by the same thread that handles updating the UI, developers can easily lock up the UI and make it unresponsive to end-users. Slow operations, such as bubble sorting a million value array, or adding ...

Strong Server-Side Parameter Validation

Most web applications require the end-user to submit form data to the server, whether through a tradition web form or via AJAX. Anytime a server receives a request with parameters, the server-side code should assume that the request is malicious. At the very least a developer should ensure that SQL and/or JavaScript code is not injected. However, a developer should know what the acceptable values are for a parameter and be able to validate against ...

CSS Targeted Only to the IPhone

One of this blogs readers, Dan Humphrey, was helpful enough to let me know that the footer position, in the new design, was not behaving correctly on the iPhone. Sure enough, when scrolling in Safari on the iPhone a position:fixed element behaves like an absolutely positioned element in other browsers. I like the fixed header and footer, and do not want to remove them, but at the same time, I dont want my site looking ...

How Forms Submit When Pressing Enter

Lately, I have been trying to perfect the x-browser behavior of pressing the enter key inside of an input field while using one of the in-page popups on Mint.com. The desired behavior is to capture the form submission and execute the same JavaScript action as is triggered by the call-to-action button. So, first I did some research trying to find out how the HTML specifications dictate that forms should behave. Unfortunately, I did not ...