Will Chrome optimize your object factories

… or does it make sense to use new or Object.create anymore?

We all love and use factories and object literals in our JS code. It’s clean, readable, there’s little space for errors and (the best of all) it allows private state. (Check here if private members in Javascript is something new to you.)

But there’s something worrying about them... Check out the following code:

It looks like we’re creating new add , sub and getVal functions over and over again. Just so they can have a separate closure scope with separate private variables (some more about this here).

Hey, but maybe Chrome’s virtual machine can optimize this stuff?

Can Chrome optimize it?

… and what is a real performance impact of using this technique? Is it really a performance problem or is it a marginal issue? Let’s check it out.

I’ve prepared a quick benchmark to test it. What I was looking for is a memory footprint differences between good ol’ prototypes with new, Object.create and closure with object literal.

Chrome has pretty nifty dev-tools with memory profiler and a quite well optimized virtual machine. So we’ll be using that. If they don’t have it optimized, then probably no other browser has.

Using prototypes

Let’s start with benchmark code. It’s pretty simple and looks more or less like this:

…full code here

It creates 1,000,000 objects with few fields and methods so we can get a bit more realistic results. Call to setInterval and method calls are there so the browser has no chance to remove it due to ‘Dead code elimination’.

Of course, all other optimizations are allowed. That’s exactly what we want to find out. If the browser has somehow optimized this stuff, so we don’t have to.

Let’s run the benchmark, take memory snapshot and looks what’s there:

As you can see we have used 58MB of memory for our dummy objects. And 10 MB of it is used by the array just to keep references to the instances. We shouldn’t really count this in. All of methods are inside shared prototype object (it has the same memory address: __proto__ = @2121167 ). This result will be our starting point. Nothing is wasted, all functions are reused (…and there’s no private state).

Using closure and object literal

This is probably the most elegant solution. It’s very readable, allows for private state and is nicely hidden from the outside. But what’s the memory footprint?

Now, the heap size is huge. We’re using 490MB of memory for the same 1,000,000 objects.

And here are file sizes of the heap dumps:

107M Proto-1000000.heapsnapshot

800M Closure-1000000.heapsnapshot

This alone shows how huge is the difference.

If you check the profiler output you’ll see, that we have a separate instance for each method with a copy of the same code. Every add , getVal , etc. has a distinct memory address. Nothing is optimized here (and I really doubt you can safely do it, to be honest).

Now, for the completeness, let’s check how Object.create behaves.

Using Object.create

More modern than new and less elegant than closures. We’re using common base object with all methods (almost like with new) and a small factory using customizer to add instance variables:

We’ll declare all variables as writable, just to be fair with prototypes. And here are the results:

It’s 66MB. Not bad. Almost the same as the new operator. We still reuse all functions code, thanks to the same __proto__ instance and don’t get any unneeded duplicates.

The verdict

Giving a clear recommendation to use one technique over the other is difficult here.

There’s definitely a memory footprint penalty for using closures and object literals. But in 99% of cases you won’t be instantiating so many of them that it becomes a problem. Also GC should usually clean it up, when they are no longer needed.

What you get though is nice, readable code and total privacy, unless you make something public.

On the other side. If what you really need is raw performance, maybe hiding new or Object.create inside some factory is a way to go. But as always “Premature optimization is the root of all evil”, so maybe it’s not worth it.

There’s also a kind of a middle ground here: use prototypes and hide all private members by declaring them inside constructor (check Privileged section in Douglas Crockford’s article).