6 ms·
Writing Fast, Memory-Efficient JavaScript
- jlongster 14y agoThis is good stuff. As I'm working on my game for github's game off, I was thinking about writing something similar. It doesn't bother me that's it's V8-centric, because devs are going to write about what they know the best. My article probably would have been SpiderMonkey focused. Not sure I'll write it anymore though, this seems to have most of what I was going to say! EDIT: After reading the article in more details, there are a few things I think it misses. My focus is more on games though. I still might write another article.
- strager 14y agoI would love to read an article about optimizing for SpiderMonkey, or at least explaining what optimizations SpiderMonkey does differently than V8.
- tantalor 14y ago> Never use delete. Ever. To "delete" is appropriate for hash-like structures, i.e., key-value maps. The runtime can't optimize these anyway; they will always be "generic slow objects". Plus, delete is the only way to remove the key, otherwise your hash will only grow in size, and you'd store a lot of "null" values for no reason that you'd have to explicitly filter.
- asolove 14y agoFor an in-depth look at what v8 does and doesn't do to optimize your code, see Vyacheslav Egorov's hilarious JSConf talk: http://blip.tv/file/6124796 http://blip.tv/file/6124796
- wizard_2 14y agoOne of my favorite talks about how an interpreter can work. It's worth watching even if you are not concerned with javascript.
- btipling 14y ago> Never use delete. Ever. ... This is horrible advice. There are plenty of things you want to delete, like references to elements when you don't need them anymore. A quick search of the Closure Library, jQuery, Backbone, Knockout, Angular.js, and ember.js found many uses of delete. Burn this article in a fire. As for the supposed performance difference, let's see a jsperf on that. Edit found one: http://jsperf.com/delete-vs-undefined-vs-null/6 http://jsperf.com/delete-vs-undefined-vs-null/6 Delete is a little slower, certainly not enough to warrant the 'never' emphasis.
- gb 14y agoCertainly delete can be useful, but nulling a property has almost the same effect (apart from hasOwnProperty still returning true) - if you're looking at optimising at the level this article is talking about avoiding delete might well be sensible.
- btipling 14y agoThis could also be horrible advice, because now you're mixing types which will make your code a little bit more complex, and you'll iterate over this null and have to deal with it. If you have an object property set to null you'll iterate over it, if you delete it you wont. As for the performance improvements, let's see the jsperf. https://gist.github.com/4018282 https://gist.github.com/4018282 Edit: I found a jsperf: http://jsperf.com/delete-vs-undefined-vs-null/6 http://jsperf.com/delete-vs-undefined-vs-null/6 Delete is a little slower, but setting null can be too, and setting undefined is the fastest for me in stable chrome.
- donpark 14y agoI think the better take away might be: avoid changing the structure of 'hot' objects at runtime. JS engines will zero-in on these 'hot' objects and attempt to optimize access to it, a task which will be helped if object doesn't change in structure over its life-time. 'delete' will trigger such a structure change. By structure in context of JS, one should think inferrable structure like always setting .a to a Number then .b to a String after instantiating an object.
- strager 14y agoI'd love to see something like this for Apple's mobile Safari browser (on iOS).
- gioele 14y agoThe title should be "Writing JavaScript code that turns out to be fast and memory-efficient in the 2012 editions of JS engines". When discussing the efficiency of a language, especially an interpreted language, one must always take into account the peculiarities of the used VM. And be sure that today's optimisations may be "pessimizations" in the future (see the many Linux optimisations that are being removed in the last years).
- mmagin 14y agoAlthough it is possible that virtual machines change more rapidly than physical machines, isn't this also true for languages more directly targeting a physical machine, e.g. C? I suppose what you're really getting at is that in JS we are subject to the whims of BOTH the compiler and the VM on the target browser?
- tolmasky 14y agoI can personally attest from first hand experience that "code rot" due to not taking advantage of the peculiarities of the current JS VM (and yesterday's "techniques" no longer being suitable) are far more commonplace than in any other programming environment I've dealt with. Also of note -- with C you make your product, compile it, ship it and largely forget about it. Its rare that PC games get slower, even if compilers change, because you don't keep recompiling it. However, if you make a JS game, that thing is interpreted from scratch every time its loaded. So if I make a JS game and ship it, the performance characteristics have a higher chance of changing in unexpected ways on me long after I've moved on. (Note: This is simply a response to this particular aspect of performance tuning JS, I am obviously not getting into the benefits of interpretation which may very well outweigh these costs.)
- masklinn 14y ago> isn't this also true for languages more directly targeting a physical machine, e.g. C? No, because the core architecture is very stable and optimizes for existing programs, which uses the existing quirks of the previous architecture. Not so for JS VMs.
- deleted 14y ago
- MatthewPhillips 14y agoV8 is not the only javascript engine.
- ben336 14y agoNo, but modern javascript engines share many traits that make these tips generally relevant across engines (although they may be more or less true for specific engines and there may be exceptions) The author is clear that the article is focused on V8. Here's a similar link from microsoft describing optimization suggestions for its Chakra engine that makes very similar recommendations: http://msdn.microsoft.com/en-us/library/windows/apps/hh781219.aspx http://msdn.microsoft.com/en-us/library/windows/apps/hh78121...
- jdavid 14y agoI think this guy makes an interesting point about performance, related issues stemming from using Delete. However, maybe the proper advice would be to Google and other folks who optimize javascripts execution to improve the handling of Delete, because is a necessary feature of frameworks.
- lenkite 14y agoAFAIK, JQuery HTML constructors use document fragments behind the scenes. See http://www.bennadel.com/blog/2281-jQuery-Appends-Multiple-Elements-Using-Efficient-Document-Fragments.htm http://www.bennadel.com/blog/2281-jQuery-Appends-Multiple-El... . No need for explicit document.createDocumentFragment
- k3n 14y agoThat's internally in jQuery though, which does you no good at all if you're invoking DOM manipulation methods yourself -- such as the example in the article, the code is calling append() inside of a loop. Each one of those calls has no knowledge of the other though, and so it cannot possible do this for you.
- cmwelsh 14y agoAvoiding nested anonymous functions is good for more reasons than listed in the article. The article lists closures holding references to the closed-over variables as being a source of wasted memory. Another point is the fact that anonymous variables require memory allocation each time they are created: // Uses more memory: Foo.prototype.someFunction = function () { ;[2, 5, 9].forEach(function (element, index, array) { console.log("a[" + index + "] = " + element) }) } The function will be created every time the outer forEach loop is called. // Uses less memory: Foo.prototype.logArrayElements = function (element, index, array) { console.log("a[" + index + "] = " + element) } Foo.prototype.someFunction = function () { ;[2, 5, 9].forEach(this.logArrayElements) } Save your created functions for later to save memory.
- btipling 14y agoWhy an expression and not simply `function logArrayElements`? If you do the latter you'll see more information if you wanted to introspect (toString on the function, or in an error traceback).
- cmwelsh 14y agoI adapted this from some game engine code. I have updated my example to show why I wasn't using a `function` statement. Thanks.
- isntitvacant 14y agoIn both examples, the function is only allocated once, no matter how it's instantiated. Where you have to be careful is if you have a function that's being called repeatedly and it contains a function instantiation -- that function will be reallocated each time. [1,2,3].forEach(function(x) { return (function(a, b) { return a * b })(x, 2) }) Will repeatedly allocate that inner multiplication function, vs: mul = function(a, b) { return a * b } ;[1,2,3].forEach(function(x) { return mul(x, 2) }) Will only allocate that multiplication function once.
- 14y ago