Skip to content
Tags

canvas, firebug, html5, javascript, profiling

Profiling Built-In JavaScript Functions with Firebug

March 26, 2011

Firebug is a Web development tool for Firefox.  Among other things, it lets you profile your JavaScript code to find performance bottlenecks.

To get started, simply go to the Firebug Web site, install the plugin, load a page in Firefox and activate Firebug.  Click the Profile button under the Console tab once to start profiling, and again to stop it.  Firebug will display a list of functions, the number of times they were called, and the time spent in each one.

For example, here is a page that repeatedly draws a red rectangle and blue circle on the new HTML5 canvas:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Profiling Example</title>
    </head>
    <body>

Let’s assume your code is taking a long time to execute.  Running the profile produces these results:

spacer

Click to enlarge

This isn’t very useful because only user-defined functions show up.  There is only one significant function here so there’s nothing to compare.  If there were some way to profile built-in JavaScript functions, we might get a better idea of which parts of the code are running slowly.

Note: This is a contrived example written to illustrate a point.  It would be just effective, and probably a better design overall, to extract two methods named drawRectangle() and drawCircle().  See Extract Method.

As a workaround, you could wrap some of the native functions and call the wrappers in your program code, like this:

function drawShapes() {
    var canvasElement = document.getElementById('canvasElement');
    var context = canvasElement.getContext('2d');

    context.fillStyle = 'rgb(255, 0, 0)';

    // Draw a red rectangle many times.
    for (var i = 0; i < 1000; i++)
    {
        fillRect(context, 30, 30, 50, 50);
    }

   context.fillStyle = 'rgb(0, 0, 255)';

    // Draw a blue circle many times.
    for (var i = 0; i < 1000; i++)
    {
        context.beginPath();
        context.arc(70, 70, 15, Math.PI * 2, 0, true);
        context.closePath();
        fill(context);
    }
}

function fillRect(context, x, y, w, h) {
    context.fillRect(30, 30, 50, 50);
}

function fill(context) {
    context.fill();
}

But that would impact your design and create unnecessary overhead.  Ideally, you’ll want a solution that’s only active during debugging and doesn’t affect your production script.  One way to do this is to write overrides for the native functions and store them in their own .js file (don’t forget to reference the script file in the HTML page):

if (window.console.firebug !== undefined)
{
    var p = CanvasRenderingContext2D.prototype;

    p._fillRect = p.fillRect;
    p.fillRect = function (x, y, w, h) { this._fillRect(x, y, w, h) };

    p._fill = p.fill;
    p.fill = function () { this._fill() };
}

What we’re doing here is saving the original function by assigning it to another function with the same name, prefixed with an underscore.  Then we’re writing over the original with our own function that does nothing but wrap the old one.  This is enough to make it appear in the Firebug profiling results.

spacer

Click to enlarge

The beauty of this approach is that it only runs when the Firebug console is turned on.  When it’s not, the conditional check fails and the code block is not executed.  The check also fails in other browsers such as IE9 and Chrome 11 beta, which is exactly what we want.

One disadvantage is that you have to write a separate function for each native function you want to override.  In the above example, a significant amount of time is probably spent in context.arc(), but we didn’t override it so there’s no way to tell.  It may be possible to override and wrap every function in a specified object automatically, but I haven’t tried that yet.  For now, I’ll leave it as an exercise for the reader.

Like this:

Like
Be the first to like this.

From → Uncategorized

Leave a Comment

Leave a Reply Cancel reply

Fill in your details below or click an icon to log in:

spacer
spacer

You are commenting using your WordPress.com account. ( Log Out / Change )

spacer

You are commenting using your Twitter account. ( Log Out / Change )

spacer

You are commenting using your Facebook account. ( Log Out / Change )

Cancel

Connecting to %s

« An HTML5 Music Visualizer for Dev:Unplugged
Workaround for NullReferenceException in DBComparer »
Follow

Get every new post delivered to your Inbox.

Powered by WordPress.com
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.