Jump to content

How to measure the speed of JavaScript execution

+ 2
  MaryO's Photo
Posted Nov 10 2009 03:08 PM

If you're curious about the time it takes for your page to load and were wondering if there was something that could tell you what's going on besides human observation, then this excerpt from Even Faster Web Sites will get you pointed in the right direction.


The easiest, most straightforward, and probably least precise way to measure latency is via human observation; simply use the application on your target platforms and ensure that performance is adequate. Since ensuring adequate human interface performance is only about pleasing humans, this is actually a fine way to perform such measurements (obviously, few humans will be able to quantify delays reliably in terms of precise whole or fractional second measurements; falling back to coarser categorizations such as “snappy,” “sluggish,” “adequate,” and so on does the job).

However, if you desire more precise measurements, there are two options you can choose: manual code instrumentation (logging) or automated code instrumentation (profiling).

Manual code instrumentation is really straightforward. Let’s say you have an event handler registered on your page, as in:

<div onclick="myJavascriptFunction()"> ... </div>

A simple way to add manual instrumentation would be to locate the definition of myJavascriptFunction() and add timing to the function:

function myJavascriptFunction() {

    var start = new Date().getMilliseconds();



    // some expensive code is here



    var stop = new Date().getMilliseconds();

    var executionTime = stop - start;

    alert("myJavascriptFunction() executed in " + executionTime +

        " milliseconds");

}

The preceding code will produce a pop-up dialog that displays the execution time; one millisecond represents 1/1,000 of a second, so 100 milliseconds represent the 0.1-second “snappiness” threshold mentioned earlier.

Note

Many browsers offer a built-in instance named console that provides a log() function (Firefox makes this available with the popular Firebug plug-in); we greatly prefer console.log() to alert().

There are tools to perform an automated measurement of code execution time, but such tools are typically used for a different purpose. Instead of being used to determine the precise execution duration of a function, such tools—called profilers—are usually used to determine the relative amount of time spent executing a set of functions; that is, they are used to find the bottleneck or slowest-running chunks of code.

The popular Firebug extension for Firefox includes a Javascript code profiler; it generates output such as that shown in Figure 2.3.

Figure 2.3. Firebug’s profiler

Attached Image

The “Time” column represents the total amount of time the Javascript interpreter spent inside a given function during the period of profiling. Often, a function invokes other functions; the “Own Time” column represents the amount of time spent inside a specific function and not any other functions that it may have invoked.

While you might think these and the other temporal-related columns represent a precise measurement of function execution time, it turns out that profilers are subject to something like the observer effect in physics: the act of observing the performance of code modifies the performance of the code.

Profilers can take two basic strategies representing a basic trade-off: either they can intrude on the code being measured by adding special code to collect performance statistics (basically automating the creation of code as in the previous listing), or they can passively monitor the runtime by checking what piece of code is being executed at a particular moment in time. Of these two approaches, the latter does less to distort the performance of the code being profiled, but at the cost of lower-quality data.

Firebug subjects results to a further distortion because its profiler executes inside Firefox’s own process, which creates the potential for it to rob the code it is measuring of performance.

Nevertheless, the “Percent” column of Firebug’s output demonstrates the power of measuring relative execution time: you can perform a high-level task in your page’s interface (e.g., click the Send button) and then check Firebug’s profiler to see which functions spent the most time executing, and focus your optimization efforts on those.

When Latency Goes Bad

It turns out that if your Javascript code ties up the browser thread for a particularly long time, most browsers will intervene and give the user the opportunity to interrupt your code. There is no standard behavior governing how browsers make the determination to give the user this opportunity. (For details on individual browser behavior, see http://www.nczonline...s-long-running/.)

The lesson is simple: don’t introduce potentially long-running, poorly performing code into your web page.

Even Faster Web Sites

Learn more about this topic from Even Faster Web Sites.

Performance is critical to the success of any web site. In this book, Steve Souders, web performance evangelist at Google and former Chief Performance Yahoo!, provides valuable techniques to help you optimize your site's performance. Souders and eight expert contributors provide best practices and pragmatic advice for improving your site's performance in three critical categories: Javascript, in the network, and in the browser.

This book contains six guest chapters contributed by Dion Almaer, Doug Crockford, Ben Galbraith, Tony Gentilcore, Dylan Schiemann, Stoyan Stefanov, Nicole Sullivan, and Nicholas C. Zakas.

See what you'll learn


Tags:
0 Subscribe


1 Reply

0
  ceautery's Photo
Posted Dec 26 2012 05:54 PM

var start = new Date().getMilliseconds();

I don't think this is correct. getMilliseconds() on a Date object returns a number between 0 and 999, not milliseconds since epoch. Your sample code will always show an execution time of less than a second for long-running scripts, or in some cases a negative number.

Instead, subtract the date objects themselves, and this will return a value in milliseconds that is the true execution time. In your sample code, just remove both instances of ".getMilliseconds()".