Hot File

Make your JavaScript apps smoother

View: 570    Dowload: 0   Comment: 0   Post by: hanhga  
Author: none   Category: Javascript   Fields: Other

0 point/1 review File has been tested

A growing amount of real-time content is being written in JavaScript. Ashley Gullen shows how to avoid pauses caused by garbage collection for a smoother experience

Introduction

This article first appeared in issue 231 of .net magazine – the world's best-selling magazine for web designers and developers.

Modern web applications often involve real-time animation and interactivity – anything from simple roll-over effects, Flash-like banners and animations implemented in HTML5 to complete games. JavaScript is faster than ever thanks to modern JIT compilers in browsers, but there’s still one problem: garbage collection (GC). This can cause pauses, stuttering and poor performance, ruining the smooth real-time experience.

But what is garbage collection? JavaScript enables you to easily create objects. However, there’s no way to delete a given object (the delete operator doesn’t count: it’s for removing properties on objects). Instead, objects are deleted automatically when no longer used.

If you create 1,000 objects but only keep references to 500 of them, at some point the browser will decide to clean up. It will see 500 are not referenced anywhere and are therefore no longer used, so it cleans them up. Some browsers implement clever techniques to make collection as quick as possible, such as generational collectors. But if you create a lot of objects in JavaScript, sooner or later the browser will have to clean up: execution is paused, it spends a while figuring out which objects are still used, and then deletes the rest.

This could take hundreds of milliseconds, or in some cases a full second or more. A smooth animation has to run at 60 frames per second, with just 16ms per frame, so this can create a noticeable pause. If lots of objects are created the browser may have to collect several times per second, making animation choppy. If you’re playing an action game in HTML5, few things are more annoying than a boss appearing, you charge up energy, time the perfect move … then the browser seizes up for a second, you miss your moment, and lose the game!

The perfect solution is to make sure nothing is allocated in the code run for each frame. But this is surprisingly difficult since many innocent looking statements create garbage. Generally the aim is to keep the rate of garbage creation low so that collections are infrequent and don’t have much to clean up.

The main technique to avoid garbage creation is to recycle objects. That means instead of creating lots of objects and throwing them away, create a few objects on startup and re-use them as long as possible. That also means keeping permanent references to objects you would have otherwise thrown away. Caches are important too, since multiple objects can be collected for recycling.

Particle effects are animated effects with the potential to create large amounts of garbage. To make sure the animation is smooth, try to recycle objects

Minimising numbers of objects created also helps improve your JavaScript's performance. Allocations and de-allocations take time; eliminating these by re-using objects can reduce the overall amount of work the browser needs to do, speeding up execution. To avoid garbage creation we need to understand which statements allocate objects – it’s obvious that the new operator creates a new object. However, there are some common shortcuts that also create new objects you should beware of:

{} // same as: new Object()[] // same as: new Array()// also creates a new function!function () { ... }

Don’t forget new allocations are made even when specifying properties or elements, which is common in JavaScript:

// Creates new object with a property{ "foo": "bar" }// Creates new array with 3 elements[1, 2, 3]// Creates 4 new arrays![[1, 2], [3, 4], [5, 6]]

Avoid all these in any code that is called frequently, especially every frame. Instead try to create the object once and permanently reference it. A simple change to make is clearing arrays, where setting the length to 0 is better than assigning a new array:

// BAD: garbage old array, create// new one, and reference thatmy_array = [];// BETTER: re-use same array objectmy_array.length = 0;

Functions can also catch you out. You may know functions also act like objects in JavaScript – but did you think that they also count as garbage? Most functions aren’t a problem, since you simply create or assign them on startup and re-use them. However, functions that return other functions (such as in closures) can be more of a problem than you think. Consider the following example using requestAnimationFrame to call a game’s tick function on an object (the vendor-specific extensions and workarounds have been omitted for clarity):

// BAD: create a whole new function// (which is garbage collected)// and call that for the next framerequestAnimationFrame((function (self) {  return function () {    self.tick();  };})(this));// BETTER: re-use the same tick function!// On startup:this.tick_function = (function (self) {  return function () {    self.tick();  };})(this);// When requesting the next call:requestAnimationFrame(this.tick_function);

Not heard of requestAnimationFrame before? Look it up, it’s better than setInterval or setTimeout for animations!

Anyway, notice how the first example creates a new function to call every tick. The second creates one on startup and re-uses it, which avoids throwing away a function every frame.

The same can be applied to objects. You can re-use an object by deleting its properties and adding them from scratch again, instead of assigning a new object. However, this is not generally a good idea. Modern browsers optimise for objects staying the same. Deleting properties causes many JavaScript engines to de-optimise and start running slower.

You should definitely avoid deleting properties in general. However, it’s a trade-off – if deleting properties saves enough garbage to reduce pauses, and it’s worth it for the lower execution speed in accessing that object, you might be able to get away with it. Bear in mind though that wherever possible, it’s better to re-use an object with the same properties and not delete anything.

Physics effects are impressive and fun, but many JS physics libraries such as Box2dWeb create huge amounts of garbage. It can be difficult to work around thi

Moving on, things become a little more difficult. Many library functions in JavaScript return new objects, which can make it difficult to avoid allocations. For example, the Array object’s slice function returns a new array based on a section of the old array. If you call slice, an allocation is made, and there’s nothing you can do about that except to avoid calling it. You can also rewrite an allocation-free version in JavaScript, but you could end up reinventing the wheel, re-implementing a lot of common JavaScript functions. It might be worth considering for hotspots of garbage creation, though.

As always the Mozilla Developer Network (MDN) is a great place to look up JavaScript library functions. For example, the MDN documentation on Array.slice states that “slice does not alter the original array, but returns a new ‘one level deep’ copy”. This is our hint that the function returns a copy (a new array) rather than modifying the original; therefore we should avoid it when minimising garbage creation. By looking up the other functions in your per-frame code path, you can also find out whether they are creating new objects or modifying in-place. They can be easy to mix up. If possible, replacing object-creating functions with ones that modify the object in-place can help reduce garbage creation. Consider the example below:

// Intention: reduce array to elements// 1, 2 and 3.// BAD: calling slice: new array is created// and old one is garbagedarr = arr.slice(1, 4);// BETTER: set length to 4, then shift// (removing first element)// Does not create any new objects!arr.length = 4;arr.shift();

Caches can also help you recycle lots of objects. For example, a particle effect may store an array of particle objects. When particles are destroyed you could just remove them from the array, where they become garbage and will later be cleaned up. A smarter choice is recycling: moving them to a ‘dead particles array’.

The Mozilla Developer Network (MDN) is the best place to look up JavaScript functions and find out whether they create new objects – potential garbage problems

When creating new particles, if the ‘dead particles array’ has any items, pop() an item and reset it to its initial state, then move it back to the active particles array. If the ‘dead particles array’ is empty you have no choice but to create a new Particle(), but that’s OK; you’ll need to create new particles on startup anyway (when the array is initially empty), and from then on they’ll be recycled.

Similar principles can be applied throughout your JavaScript. For instance, you may have a stack of objects, implemented by pushing and popping to an array. If popping from the array would garbage the object, you could consider caching it. You could also use an integer pointing at the ‘top index’ in the stack, and increment and decrement that instead of pushing and popping, recycling objects as you go. Stacks can also be an important way to work around passing new objects along in recursive functions, where as useful as the {} syntax is, it still can create a lot of garbage.

Some of the worst offenders for GC performance in JavaScript are vector objects (such as an object containing an x and y co-ordinate); JS implementations of Box2D physics often suffer from this issue. Libraries designed around such objects can create thousands of vector objects per second, often with no way to recycle them – or requiring special calls to ‘free’ them, which can be tricky to get in exactly the right places.

Often applications made with libraries like these show the worst garbage collection pauses. It’s far better to have functions operating on each co-ordinate separately – such as getX() andgetY(), which return simple numbers, rather thangetPosition(), which returns a new vector2(…). When deciding between libraries, for best performance you probably want to avoid any that use vector objects like that. Vector objects are indeed convenient, and can make your code neater and simpler, but the JavaScript language’s design makes it hard to use them without creating huge amounts of garbage – making your game or animation choppier!

So making modifications to reduce GC overhead can, sadly, make your code more complicated and difficult to follow. But with care it’s perfectly possible to craft real-time JavaScript that will make your games, effects or animations smoother and more responsive than the rest.

Make your JavaScript apps smoother

Make your JavaScript apps smoother Posted on 26-03-2014  A growing amount of real-time content is being written in JavaScript. Ashley Gullen shows how to avoid pauses caused by garbage collection for a smoother experience 5/10 570

Comment:

To comment you must be logged in members.

Files with category

  • JUnit 5 State Of The Union using java

    View: 367    Download: 0   Comment: 0   Author: none  

    JUnit 5 State Of The Union using java

    Category: Javascript
    Fields: Other

    4.5/1 review
    JUnit 5 has been under development for about 14 months now and the prototype is almost a year old. Time to summarize what happened so far, where the project stands, and where it’s going.

  • Getting Started with Dropwizard using java

    View: 362    Download: 0   Comment: 0   Author: none  

    Getting Started with Dropwizard using java

    Category: Javascript
    Fields: Other

    4.5/1 review
    Dropwizard is a framework for building RESTful web services in Java. In this tutorial we’re going to have a look at how to get started with developing a Dropwizard application by building a new service from scratch.

  • Build Query NULL Value in MySql

    View: 190    Download: 0   Comment: 0   Author: none  

    Build Query NULL Value in MySql

    Category: Javascript
    Fields: Other

    2.5/2 review
    Misunderstanding NULL is common mistake beginners do while writing MySql query. While quering in MySql they compare column name with NULL. In MySql NULL is nothing or in simple word it isUnknown Value so if you use comparison operator for NULL values...

  • Manage Your JavaScript Application State with MobX

    View: 194    Download: 0   Comment: 0   Author: none  

    Manage Your JavaScript Application State with MobX

    Category: Javascript
    Fields: Other

    2.25/2 review
    This article was peer reviewed by Michel Weststrate and Aaron Boyer. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

  • Build Bringing Pages to Life with the Web Animations API

    View: 204    Download: 0   Comment: 0   Author: none  

    Build Bringing Pages to Life with the Web Animations API

    Category: Javascript
    Fields: Other

    4.5/2 review
    This article is by guest author Dudley Storey. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

  • How to Style Google Custom Search Manually

    View: 179    Download: 0   Comment: 0   Author: none  

    How to Style Google Custom Search Manually

    Category: Javascript
    Fields: Other

    0/0 review
    Website owners very often decide on using Google’s Custom Search Engine (GCSE) for searching through their content instead of using built-in and/or custom search functionality. The reason is simple – it’s much less work, and most often it does the...

  • Test React Components Using Jest

    View: 4795    Download: 0   Comment: 0   Author: none  

    Test React Components Using Jest

    Category: Javascript
    Fields: Other

    4.5/1 review
    This article is by guest author Jack Franklin. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

  • Programming Question Reverse String without using String function

    View: 312    Download: 0   Comment: 0   Author: none  

    Programming Question Reverse String without using String function

    Category: Javascript
    Fields: Other

    0/0 review
    Write a program to reverse string without using string function. You don’t have to use any in-built string library function. This problem can be solved by multiple approaches. Let’s check it.

 
Newsletter Email

File suggestion for you

File top downloads

logo codetitle
Codetitle.com - library source code to share, download the file to the community
Copyright © 2015. All rights reserved. codetitle.com Develope by Vinagon .Ltd