3

Suppose I have a function that I need to call a lot, maybe a few thousand times on every mouse down or mouse move. It uses an instance of a function (class), called Transform:

function func1(a, b, c) {
  var t = new Transform();
  t.rotate(a);
  t.scale(b, c);
  return t.m[0];
}

So I'm creating thousands of new transforms as I call this func1 lots.

What if, instead of creating new Transform()s every time, I created a small system to allocate extra transforms only as they are needed, and re-use them:

window.Util = {
  _CachedTransforms: [],
  tempTransform: function() {
    var arr = Util._CachedTransforms;
    var temp = arr.pop();
    if (temp === undefined) return new Transform();
    return temp;
  },
  freeTransform: function(temp) {
    Util._CachedTransforms.push(temp);
  }
}

Then instead I could call func2:

function func2(a, b, c) {
  var t = Util.tempTransform();
  t.reset();
  t.rotate(a);
  t.scale(b, c);
  var result = t.m[0];
  Util.freeTransform(t);
  return result;
}

Using func2 several thousand times, new Transform is only ever called once. This might suggest a benefit, but the numbers from jsperf don't seem to suggest any.

If you want to see these two functions in action as well as the Transform class, take a look at jsperf: http://jsperf.com/transforms

And especially: http://jsperf.com/transforms/2

To simulate it occuring lots during an event, my jsperf test does:

var a;
for (var i = 0; i < 4000; i++) {
  a += func1(1, i, 3); // vs func2
}

There may be better ways to test if this is advantageous or not. Am I missing something?

More broadly, is object reuse like this still a good idea in this scenario, or ever?

migrated from codereview.stackexchange.com Jul 12 '13 at 18:01

This question came from our site for peer programmer code reviews.

1

This is a method known as "object pooling", and you are correct that it can speed up performance. Object creation is usually a fairly inexpensive task in Javascript (though Object.create can be pretty slow surprisingly in my experience), but needing to invoke the GC repeatedly can cause noticeable performance issues.

Of course, you should only optimize if you have figures that suggest you have to.

I'm kind of on the same page as Avner Shahar-Kashtan in that object creation might not even be required in this case.

7

Is there a reason you even need multiple Transform objects? Wouldn't it be simpler to have Transform be stateless, and have the rotate and scale methods simply return a transformed object? That way you don't have to worry about the state of the Transform, and can safely spawn each function on a different thread, which could lead to significant improvements.

1

Reducing the time spent allocating objects is a good idea. Its so good in fact that most javascript implementations are already doing it behind the scene. So when you try to implement your own version you just implement a less efficient version of it than the runtime is already giving you.

You can improve performance by not allocating objects. However, your method is essentially still allocating objects, you've just implemented a custom allocator. You probably can't beat the allocator already available in a good javascript implementation.

0

Considering as Javascript is single-threaded, there is no use in keeping an array of multiple instances, since there can only be one Transform object in use at a given time. Furthermore, since your usage of the tranform object is synchronous, there is no need to lock/free the instance. So in effect, you only need one instance, which can be made global, sparing you additional function calls.

function func2(a, b, c) {
  var t = Window.transformSingleton;
  t.reset();
  t.rotate(a);
  t.scale(b, c);
  var result = t.m[0];
  return result;
}

Another option would be to pass the transform object as a parameter to func2. In Javascript object arguments gets passed as references, so you are still using a single object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.