Posted on by & filed under Content - Highlights and Reviews, Web Development.

This post will give you some techniques for optimizing your game loop using browser profiling tools, thus improving the performance of your game. The various profiling tools available for the most popular browsers will be discussed, along with a description of how to effectively identify bottlenecks in performance and interpret the results.

As with any realtime application, what is most important is the ability of your central loop (the game loop) to run in a timely manner. If 60 frames per second is your goal, you had better make sure that the code in your loop is able to completely update and render your entire scene in under 16 milliseconds, or you’ll start dropping frames like Stevie Wonder browsing an art gallery on rollerskates.

The Tools

A good CPU profiler is essential in optimizing your game loop.

Fortunately, in-browser consoles and JavaScript debuggers have come a long way since the early days, and modern browsers offer some excellent profiling tools in their suite of dev tools.

Of course, there are 3rd-party JavaScript profiling tools out there (one of the better tools I would recommend is dynaTrace AJAX edition). But there is a certain satisfaction in loading up a fresh browser on any machine and getting some instant profiler gratification.

The unoptimized loop

With the intent of creating an embarrassingly poor-performing baseline, I set out to write a rather horrendous game loop.

Each iteration of the loop will render 5000 instances of the spite shown below at various positions and rotations, producing a rather hypnotizing ring of spinning spaceships. The demo in motion can be viewed here: http://moot-point.com/demos/loop/loop-unoptimized.html.

As you can see, the unoptimized game loop ended up netting an unhealthy 15 fps.

With the advance knowledge that the Profiler will be reporting statistics such as the number of function calls, and the amount of time spent within each function, it is a good idea to start out by intentionally breaking up the code into small function blocks.

In general, this approach will allow for more clear profiling results than if all code were contained within a few large functions (with the least useful case being one function potentially contributing to 100% of the CPU time, which would lead you without any obvious indication of what portion is contributing the most).

The markup:

The script:

In-browser profiling

Our first order of business is to select a browser platform from which to profile our disastrous masterpiece.

I loaded up the unoptimized code in Chrome, Firefox, and Internet Explorer 9 and kicked off their respective profiling tools.

The latest builds of Firefox and Chrome offer a modest toolset for JavaScript profiling. Interestingly enough, Internet Explorer in its 9th iteration offers one of the more fully-featured profiling reports out of all current browsers.

In general, the longer the profiler is run, the more accurate the results, so I ended up profiling each session for 30 seconds.The in-browser profiling tools do not provide much in terms of automation: we cannot automate a start/end time or total duration of the profiling session. Although this may be possible via a 3rd party tool or home-brewed macro, the sessions below are based off a simple stopwatch time of 30 seconds.

Firefox

Firefox does not offer a profiler out-of-the box; however, this functionality is available via the Firebug plugin.

Since Firebug is so ubiquitous among the developer community, for purposes of this comparison, I’m considering it to be a native browser tool.

As seen in the screenshot below, the Firefox profiler offers a rather nice assortment of statistics for each function call that profiled. Like we will see for all browser profilers, it offers a link to jump directly to the containing file and function definition.

One downside is that only a flat, non-hierarchical view of the function call tree is available. Also, Firefox only includes user-defined functions in its report. Native functions (such as DOM manipulations and native JavaScript functions) are not indicated.

Chrome

Chrome’s profiler offers an improved degree of flexibility by allowing you to toggle between both a flat view and a hierarchical tree. The hierarchical tree is shown below.

Only a minimal set of statistics are presented in the report: the time spent in a function in terms of percentage or milliseconds. Another downside is that functions that had contributed under 0.01% to the total during the profiling session are not shown in the report at all.

Nevertheless, Chrome is unique in that it offers three types of profiling: CPU profiling, CSS profiling, and a Heap Snapshot. Chrome is only current browser which can perform detailed analysis of memory usage via the Heap Snapshot.

Chrome’s Heap Snapshot is shown below. This can be quite useful for tracking down memory leaks in your application, but a more detailed look is outside the scope of this article.

Internet Explorer

Internet Explorer 9’s Developer Tools are much improved over previous iterations of the browser — a sign that Microsoft is starting to take their dev tools quite seriously!

Below is the report produced by IE9. It features a full set of statistics and allows toggling between a flat or tree view. What is also quite nice is that it categorizes the calls by Function type.

The downside is that no memory profiling is available in IE9, although a future build of Internet Explorer 10 is rumored to roll out a competitive set of memory analysis tools.

Interpreting the results

We can glean some useful information about our unoptimized code from the report above.

Since we had broken up the code into small function blocks, these reports can give us a pretty good idea of the overall CPU contribution of each function. Inclusive time gives us the amount of time spent in a function and all of its children, while Exclusive time gives us the amount of time spent within only that function itself, in terms of quickly identifying the largest contributors.

Exclusive time % gives us the best indication of problem areas right off the bat. We can see that our renderShipAt() function is taking up 35.4% of the total time spent in the game loop, so we may want to set our sights there first.

The Count column tells us how many times that function had run. We can tell that our game loop ran a total of 54 times during the profiling session. Since our loop was rendering 5,000 objects during each iteration, the child functions such as renderShip ended up running a total of 54 x 5,000 = 270,000 times. So this is clearly where we need to focus our efforts.

We can get a good idea of how long the game loop is taking by looking at the Avg time for our update(). At 527.18 ms, we are quite a ways off from our 16ms target!

Note the Anonymous function listed at the bottom row. This is actually an artifact of the FPS plugin used by the demo, which itself contributes a number of CPU cycles during each iteration of the loop. To get the truest real-world result, disable all measuring tools during the profiling session.

The Function Type will denote either User, DOM, or Built-in (native JavaScript). For DOM and Built-in functions, we are pretty much at the mercy of the browser’s implementation of these methods, so all we can do is minimize our use of these functions. In contrast, any functions labelled “User” are firmly under our own grasp.

We now have a good idea of the problem areas we need to attack in our demo app, and in the next blog piece (HTML5 Games: Fixing Our Demo) we will make the changes needed to produce the app within our 16ms target.

Safari Books Online has the content you need

Check out these HTML5 books available from Safari Books Online that will help you develop HTML5 games:

You’ll learn how to build interactive multimedia applications with HTML5 Canvas, using this new element to draw, animate, compose images, and more. You’ll also learn the best way to use existing JavaScript libraries, as well as how to incorporate related aspects such as audio and video.
Foundation HTML5 Canvas: For Games and Entertainment teaches you how to make exciting interactive games and applications using HTML5 canvas. Canvas lets you produce graphics, animations, and applications using the HTML5 and JavaScript web standards. It allows you to draw directly within the browser without the need for third-party plugins like Adobe Flash, and so canvas works perfectly across desktop and mobile devices, like the iPhone and Android.
HTML5 Games Development by Example will show you how to use latest HTML5 and CSS3 web standards to build card games, drawing games, physics games and even multiplayer games over the network. With the book you will build 6 example games with clear step-by-step tutorials.
HTML5 Canvas Cookbook begins by covering the basics of the HTML5 Canvas API and then provides techniques for handling features not directly supported by the API such as animations and canvas interactivity. It winds up by providing detailed templates for a few of the most common HTML5 canvas application.
Core HTML5 Canvas: Graphics, Animation, and Game Development presents a code-fueled, no-nonsense deep dive into that API, covering everything you need to know to implement rich and consistent web applications that run on a wide variety of operating systems and devices.
If you’re a web developer looking to use this new version of HTML, you might be wondering how much has really changed. Head First HTML5 Programming introduces the key features — including improved text elements, audio and video tags, geolocation, and the Canvas drawing surface — and uses concrete examples and exercises to apply and reinforce these concepts.

About this author

Kevin Moot has had an interest in computer graphics since creating games as a wee lad on his Apple IIe – complete with its vast array of six colors and a mind boggling 280×192 resolution. Kevin has worked with HTML5’s canvas technology for several cutting-edge websites and counts HTML/CSS, JavaScript and .NET among his specialties. He currently works at The Nerdery as an interactive software developer.

Tags: CPU profiling, CSS profiling, Game Loop, Games, Heap Snapshot, html5, Javascript,

Trackbacks/Pingbacks

  1.  HTML5 Games: Fixing Our Demo | Safari Books Online's Official Blog