.

Tags:

A common pattern to speed-up the performance of your JavaScript code is to leverage the optimized property access found in modern JavaScript engines. In fact, fast property access is a key in design elements of V8. It is also achieved in JavaScriptCore, the default engine behind WebKit, via polymorphic inline cache. Firefox enjoys the same speed-up also through the same polymorphic inline cache available in its JägerMonkey project.

How would you take advantage of this feature? It’s very simple. In practice, it’s a matter of being careful with object construction. For example, rather than doing the following:

var universe = {
  answer: 42
};
// do something else
universe.panic = false;

it’s recommended to implement it this way:

var universe = {
  answer: 42,
  panic: true
};
// do something else
universe.panic = false;

Basically, try to keep the object structure unchanged (obviously it may require some change in your logic). If you don’t know the value of a certain property, e.g. panic in the above example, that’s totally fine. You can always change the property value later, but you would help the JavaScript engine if you avoid adding and removing properties after the object is created.

For real-world examples, check out Esprima development. In revision 4f9af77ddc, carefully fixing the structure of token object improves Firefox 9 performance. The similar trick is used to regain the speed as a new feature was introduced.

Before you go wild and obfuscate your code to take advantage of this speedier property access, remember one thing: always optimize responsibly. First, make sure that the bottleneck is not somewhere else. In addition, avoid the temptation of a higher performant variant if that will significantly reduce the readability of the code.

OK properties, off you go!

Ariya Hidayat

Software Provocateur
These days, I promote software craftsmanship around web technologies. If you like this article, read also other similar blog posts and follow me @ariyahidayat.

Latest posts by Ariya Hidayat (see all)

  • lfranchi

    Interesting post, thanks!

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You’re welcome!

  • lfranchi

    Interesting post, thanks!

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You’re welcome!

  • IvanDM

    First time I hear someone actually explaining how to improve JS performance in correlation with Browser internals. More tricks to share?

    • http://ariya.ofilabs.com/ Ariya Hidayat

      That’s the plan!

  • IvanDM

    First time I hear someone actually explaining how to improve JS performance in correlation with Browser internals. More tricks to share?

    • http://ariya.ofilabs.com/ Ariya Hidayat

      That’s the plan!

  • http://twitter.com/vishalkrsingh Vishal Kumar Singh

    Have been writing JS codes for years, but I never knew this, @ariya:disqus would love to see more SMALL posts like this. Thank you.

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You’re welcome, and I’ll try to write more in the future!

  • http://twitter.com/vishalkrsingh Vishal Kumar Singh

    Have been writing JS codes for years, but I never knew this, @ariya:disqus would love to see more SMALL posts like this. Thank you.

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You’re welcome, and I’ll try to write more in the future!

  • Akram El Assas

    Many thanks for this tip!

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You are welcome!

  • Akram El Assas

    Many thanks for this tip!

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You are welcome!

  • Asen Bozhilov

    For a statically optimizations is applicable, but I can’t imagine how many lines should be the program, to be optimized in that way. 
    Usually when the optimization would matter you are not able to use that approach. The most often use case is for mixin patterns, when you have to add dynamicly properties. In this case you can’t use such a reflective way to optimize the code. The only one way would be `eval` but it’s definitely not faster than square bracket and assignment expression. 

    By these reasons I would consider that approach is a micro optimization. I always initialize my properties even and they not intended to have meaningful value. I do that mostly for readability and maintainability not so for optimizations.   

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Fair enough. I don’t advocate the approach as a general trick. Maybe the included disclaimer did not emphasize that enough? For the exemplary commit in Esprima, it gives a significant gain (without reducing the readability) because the main loop inside the tokenizer is basically invoked a gazillion times.

  • Asen Bozhilov

    For a statically optimizations is applicable, but I can’t imagine how many lines should be the program, to be optimized in that way. 
    Usually when the optimization would matter you are not able to use that approach. The most often use case is for mixin patterns, when you have to add dynamicly properties. In this case you can’t use such a reflective way to optimize the code. The only one way would be `eval` but it’s definitely not faster than square bracket and assignment expression. 

    By these reasons I would consider that approach is a micro optimization. I always initialize my properties even and they not intended to have meaningful value. I do that mostly for readability and maintainability not so for optimizations.   

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Fair enough. I don’t advocate the approach as a general trick. Maybe the included disclaimer did not emphasize that enough? For the exemplary commit in Esprima, it gives a significant gain (without reducing the readability) because the main loop inside the tokenizer is basically invoked a gazillion times.

  • mraleph

    For inline-cache (at least in V8) it does not matter how you build your object as long as (1) resulting object is in “fast properties” mode and (2) IC site is monomorphic (that is sees objects of a single shape).

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Thanks for the additional info. That explains why the mentioned Esprima commit did not affect Chrome/V8.

  • mraleph

    For inline-cache (at least in V8) it does not matter how you build your object as long as (1) resulting object is in “fast properties” mode and (2) IC site is monomorphic (that is sees objects of a single shape).

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Thanks for the additional info. That explains why the mentioned Esprima commit did not affect Chrome/V8.

  • http://twitter.com/seasoup seasoup

    From what I can see this is true for Chrome, but not for Firefox.  Running a for loop 1,000,000 times in FF with both versions took ~42ms in FF.  In chrome, the first version took ~70ms, and the second one took ~22ms on my system.  So, x3 increase for chrome.

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Can you confirm that your benchmark loop is not affected by dead code elimination?

  • http://twitter.com/seasoup seasoup

    From what I can see this is true for Chrome, but not for Firefox.  Running a for loop 1,000,000 times in FF with both versions took ~42ms in FF.  In chrome, the first version took ~70ms, and the second one took ~22ms on my system.  So, x3 increase for chrome.

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Can you confirm that your benchmark loop is not affected by dead code elimination?