KEMBAR78
Improving Game Performance in the Browser | PPTX
Increasing the 
performance of Web 
based games 
Michael “Mickey” MacDonald 
Indie Game Developer & @ScruffyFurn 
Extreme Video Game Geek
Areas we will cover 
• Loading and caching for performance 
• Using Web Workers 
• Audio performance tricks 
• Optimizing drawing 
• Other miscellaneous Tips 
Windows Game On
• Preload game assets! 
• Have assets available when needed 
• Increases performance by not loading assets during game cycle 
• Most common libraries are now offering a preloader feature 
• PreloadJS - http://createjs.com/#!/PreloadJS 
• Add preloading to any project 
• Very easy to setup and use
var queue = new createjs.LoadQueue(); 
queue.on("complete", handleComplete, this); 
queue.loadManifest([ 
{ id: "myImage", src: "path/to/myImage.jpg" } 
]); 
function handleComplete() { 
var image = queue.getResult("myImage"); 
document.body.appendChild(image); 
}
• Compress assets to help reduce size of download 
• When choosing an asset’s format keep compression in mind 
• There are many different audio, video and image formats supported by 
modern browsers
Format Typical Compression Ratios Description 
GIF 4:1 - 10:1 
Lossless for images <=== 256 colors. Works 
best for flat color, sharp-edged art. 
Horizontally oriented bands of color compress 
better than vertically oriented bands. 
JPEG (High) 10:1 - 20:1 
High quality - has little or no loss in image 
quality with continuous tone originals. Worse 
results for flat color and sharp-edge art. 
JPEG (Medium) 30:1 - 50:1 
Moderate quality - usually the best choice for 
the Web. 
JPEG (Low) 60:1 - 100:1 
Poor quality - suitable for thumbnails and 
previews. Visible blockiness (pixelation). 
PNG 10-30% smaller than GIFs 
PNG's behave similarly to GIFs only better; 
they work best with flat-color, sharp-edged 
art.
• Always preload and cache heavily used sound effects 
• Compress your audio as much as you can without effecting the quality 
• If possible use a low latency plugin 
• SoundJS - http://www.createjs.com/#!/SoundJS
• JavaScript’s memory model is built on a technology known as a Garbage 
Collector 
• Garbage collection cost performance 
• Garbage Collector decides when memory should be reclaimed 
• You have no control when it decides to run
• Reducing memory churn will cut down the amount of times the garbage 
collector runs 
Heavy memory churn – 
A more ideal memory usage -
• Cut down memory churn by using Object Pooling 
• Reuse objects from the pool instead of creating new ones 
• Object are never deleted from code and won’t be garbage collected
Simple example: Create a pool of objects using array 
• Pre-construct and populate an object array at load. 
• Like an array of 20 projectiles 
• Instead of create an new projectile when firing: 
var p = new Projectile(); 
• Setup a factory function like: 
var p = new GetNewProjectile();
• Return it to the pool when no longer needed 
if (p.collidingWith(enemy)) // It Hit! 
freeProjectile(p); // return it to the pool 
• Once return to the pool make sure to reinitialize all of the values back to 
an original state
• Cache values from calculations 
• Things like transforms can be cached to save from making more than one call 
var playerTransform = player.getPlayerTransform(); 
• If you use it more than once, it is a candidate for caching
• When executing scripts in an HTML page, the page becomes 
unresponsive until the script is finished. 
• A web worker allows JavaScript code to run in the background, without 
affecting the performance of the page.
• Always check for web worker support before creating one 
if (typeof (Worker) !== "undefined") { 
// Yes! Web worker support! 
// Some code..... 
} else { 
// Sorry! No Web Worker support.. 
}
First create a JavaScript file we want to run as our Web Worker 
var i = 0; 
function timedCount() { 
i = i + 1; 
postMessage(i); 
setTimeout("timedCount()", 500); 
} 
timedCount();
Create a Web Worker Object 
if (typeof (w) == "undefined") { 
w = new Worker("demo_workers.js"); 
}
Now we can send & receive messages from our Web Worker 
Below we add an “onmessage” event listener to our Web Worker 
w.onmessage = function (event) { 
document.getElementById("result").innerHTML = 
event.data; 
};
Terminate a Web Worker 
w.terminate(); 
Reusing the Web Worker 
w = undefined; 
• You can reuse a worker after it has been terminated
Demo 
Simple Web Worker Example
• Use whole number pixel rendering 
ctx.drawImage(myImage, 0.3, 0.5); 
• CSS for large background images 
• Don’t scale images in drawImage
• Use multiplication instead of division 
• Use if…else instead of switch case 
• Keep your game update loops clean 
• Avoid frequent calls to localStorage 
• Avoid For each loops in events 
• If possible use WebGL (Even for 2D) 
• Use min versions of libraries where possible
wootstudio.ca
Windows Game On 
Thank you! 
Happy Coding
©2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, Office, Azure, System Center, Dynamics and other product names are or may be registered trademarks and/or trademarks in the 
U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft 
must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after 
the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.

Improving Game Performance in the Browser

  • 1.
    Increasing the performanceof Web based games Michael “Mickey” MacDonald Indie Game Developer & @ScruffyFurn Extreme Video Game Geek
  • 2.
    Areas we willcover • Loading and caching for performance • Using Web Workers • Audio performance tricks • Optimizing drawing • Other miscellaneous Tips Windows Game On
  • 3.
    • Preload gameassets! • Have assets available when needed • Increases performance by not loading assets during game cycle • Most common libraries are now offering a preloader feature • PreloadJS - http://createjs.com/#!/PreloadJS • Add preloading to any project • Very easy to setup and use
  • 4.
    var queue =new createjs.LoadQueue(); queue.on("complete", handleComplete, this); queue.loadManifest([ { id: "myImage", src: "path/to/myImage.jpg" } ]); function handleComplete() { var image = queue.getResult("myImage"); document.body.appendChild(image); }
  • 5.
    • Compress assetsto help reduce size of download • When choosing an asset’s format keep compression in mind • There are many different audio, video and image formats supported by modern browsers
  • 6.
    Format Typical CompressionRatios Description GIF 4:1 - 10:1 Lossless for images <=== 256 colors. Works best for flat color, sharp-edged art. Horizontally oriented bands of color compress better than vertically oriented bands. JPEG (High) 10:1 - 20:1 High quality - has little or no loss in image quality with continuous tone originals. Worse results for flat color and sharp-edge art. JPEG (Medium) 30:1 - 50:1 Moderate quality - usually the best choice for the Web. JPEG (Low) 60:1 - 100:1 Poor quality - suitable for thumbnails and previews. Visible blockiness (pixelation). PNG 10-30% smaller than GIFs PNG's behave similarly to GIFs only better; they work best with flat-color, sharp-edged art.
  • 7.
    • Always preloadand cache heavily used sound effects • Compress your audio as much as you can without effecting the quality • If possible use a low latency plugin • SoundJS - http://www.createjs.com/#!/SoundJS
  • 8.
    • JavaScript’s memorymodel is built on a technology known as a Garbage Collector • Garbage collection cost performance • Garbage Collector decides when memory should be reclaimed • You have no control when it decides to run
  • 9.
    • Reducing memorychurn will cut down the amount of times the garbage collector runs Heavy memory churn – A more ideal memory usage -
  • 10.
    • Cut downmemory churn by using Object Pooling • Reuse objects from the pool instead of creating new ones • Object are never deleted from code and won’t be garbage collected
  • 11.
    Simple example: Createa pool of objects using array • Pre-construct and populate an object array at load. • Like an array of 20 projectiles • Instead of create an new projectile when firing: var p = new Projectile(); • Setup a factory function like: var p = new GetNewProjectile();
  • 12.
    • Return itto the pool when no longer needed if (p.collidingWith(enemy)) // It Hit! freeProjectile(p); // return it to the pool • Once return to the pool make sure to reinitialize all of the values back to an original state
  • 13.
    • Cache valuesfrom calculations • Things like transforms can be cached to save from making more than one call var playerTransform = player.getPlayerTransform(); • If you use it more than once, it is a candidate for caching
  • 14.
    • When executingscripts in an HTML page, the page becomes unresponsive until the script is finished. • A web worker allows JavaScript code to run in the background, without affecting the performance of the page.
  • 15.
    • Always checkfor web worker support before creating one if (typeof (Worker) !== "undefined") { // Yes! Web worker support! // Some code..... } else { // Sorry! No Web Worker support.. }
  • 16.
    First create aJavaScript file we want to run as our Web Worker var i = 0; function timedCount() { i = i + 1; postMessage(i); setTimeout("timedCount()", 500); } timedCount();
  • 17.
    Create a WebWorker Object if (typeof (w) == "undefined") { w = new Worker("demo_workers.js"); }
  • 18.
    Now we cansend & receive messages from our Web Worker Below we add an “onmessage” event listener to our Web Worker w.onmessage = function (event) { document.getElementById("result").innerHTML = event.data; };
  • 19.
    Terminate a WebWorker w.terminate(); Reusing the Web Worker w = undefined; • You can reuse a worker after it has been terminated
  • 20.
    Demo Simple WebWorker Example
  • 21.
    • Use wholenumber pixel rendering ctx.drawImage(myImage, 0.3, 0.5); • CSS for large background images • Don’t scale images in drawImage
  • 22.
    • Use multiplicationinstead of division • Use if…else instead of switch case • Keep your game update loops clean • Avoid frequent calls to localStorage • Avoid For each loops in events • If possible use WebGL (Even for 2D) • Use min versions of libraries where possible
  • 23.
  • 24.
    Windows Game On Thank you! Happy Coding
  • 25.
    ©2013 Microsoft Corporation.All rights reserved. Microsoft, Windows, Office, Azure, System Center, Dynamics and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.

Editor's Notes

  • #8 Consistant cross-browser support for audio is currently a mess in HTML5, but SoundJS works to abstract away the problems and makes adding sound to your games or rich experiences much easier. You can query for capabilities, then specify and prioritize what APIs, plugins, and features are leveraged for specific devices or browsers.
  • #9 Garbage Collector system, however, manages this task on behalf of the programmer, meaning that objects aren’t directly freed from memory when the programmer dereferences it, but rather at a later time when the GC’s heuristics decide that it would be beneficial to do so. This decision process requires that the GC execute some statistical analysis on active and inactive objects, which takes a block of time to perform. The process in which a GC reclaims memory is not free, it usually cuts into your available performance by taking a block of time to do its work; alongside that, the system itself makes the decision when to run. You have no control over this action, a GC pulse can occur at any time during code execution, which will block code execution until it’s completed. The duration of this pulse is generally unknown to you; will take some amount of time to run, depending on how your program is utilizing memory at any given point. Avoid internal methods creating garbage There are various JavaScript methods that create new objects rather than modifying the existing one. This includes: Array.slice, Array.splice,Function.bind
  • #10 the key to reducing the amount of time that the Garbage Collector takes from your application lies in eliminating as many cases of excessive object creation and release as you can. This process of creating/freeing object frequently is called “memory churn”. If you can reduce memory churn during the lifetime of your application, you also reduce the amount of time GC takes from your execution. This means you need to remove / reduce the number of created and destroyed objects, effectively, you have to stop allocating memory
  • #11 In simple terms, object pooling is the process of retaining a set of unused objects which share a type. When you need a new object for your code, rather than allocating a new one from the system Memory Heap, you instead recycle one of the unused objects from the pool. Once the external code is done with the object, rather than releasing it to main memory, it is returned to the pool. Because the object is never dereferenced (aka deleted) from code it won’t be garbage collected. Utilizing object pools puts control of memory back in the hands of the programmer, reducing the influence of the garbage collector on performance.
  • #12 This will avoid construction by just returning one of the pre-constructed objects from the array, or if there are none available, fall back to constructing another bullet - essentially automatically expanding the pool.
  • #13 Once you’re done with the projectile, you need to return it to the pool: One thing to remember here is the object coming back from the pool isn’t necessarily a new one, it could have just been returned to the pool. That means you need to be careful to reinitialize all of the values back to an original state.
  • #15 When executing scripts in an HTML page, the page becomes unresponsive until the script is finished. A web worker allows JavaScript code to run in the background, independently of other scripts, without affecting the performance of the page. You can continue to do whatever you want: clicking, selecting things, etc., while the web worker runs in the background.
  • #17 Here, we create a script that counts. The script is stored in the file demoworker.js The important part of the code above is the postMessage() method - which is used to post a message back to the HTML page. Note: Normally web workers are not used for such simple scripts, but for more CPU intensive tasks. he "demoworker.js" file:
  • #18 Now that we have the code we want to run with our Web Worker, we need to call it from an HTML page. These lines checks if the worker already exists, if not - it creates a new web worker object and runs the code in "demoworkers.js":
  • #19 When the web worker posts a message, the code within the event listener is executed. The data from the web worker is stored in event.data.
  • #20 When a web worker object is created, it will continue to listen for messages (even after the external script is finished) until it is terminated. To terminate a web worker, and free browser/computer resources, use the terminate() method: If you set the worker variable to undefined, after it has been terminated, you can reuse the code:
  • #21 http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_webworker Or show the code in simple web worker example
  • #22 Drawing on HTML5 2D canvas is the biggest bottleneck in most JavaScript games Sub-pixel rendering occurs when you render objects on a canvas without whole values. This causes the browser to do extra calculations to create the anti-aliasing effect. To avoid this, make sure to round all co-ordinates used in calls to drawImage using something like Math.floor  If like most games you have a static background image, use a plain DIV element with a CSS background property and position it under the canvas. This will avoid drawing a large image to the canvas on every tick. Cache various sizes of your images on an offscreen canvas when loading as opposed to constantly scaling them in drawImage.
  • #23 LocalStorage uses file IO and blocks the main thread to retrieve and save data Easier said than done but giving all the heavy graphics lifting to the GPU will free up the CPU for greater good. Even though WebGL is 3D, you can use it to draw 2D surfaces. There are some libraries out there that aim to abstract the drawing contexts. ThreeJS, BabylonJS