5 ms·
Really great! Some notes that popped out for me are that to always cache the .length property for any array or arguments: function doesntLeakArguments()
by binarymax 12y ago
Really great! Some notes that popped out for me are that to always cache the .length property for any array or arguments:
function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return args;
}
becomes:
function doesntLeakArguments() {
var len = arguments.length;
var args = new Array(len);
for(var i = 0; i < len; ++i) {
args[i] = arguments[i];
}
return args;
}
And also, if you've got a switch statement with more than 128 cases, you've probably got bigger problems on your hands than v8 optimizations.
I see some things in here that I can start switching to immediately for some of my node modules.
- phpnode 12y agoThe article is "optimisation killers", you're right about caching the array length lookup check being faster, but it doesn't kill V8's ability to optimise functions like the rest of the examples do
- pdw 12y agoHuge switches are common in the inner loop of emulators and interpreters. They tend to end up with a 256-case switch to handle the next byte in the instruction stream.
- binarymax 12y agoI understand that use case, but in my opinion it would be much cleaner (and speculating faster) to have an 256-slot array...and routing with opcodes[byte.charCodeAt(0)](); or something similar.
- arcatek 12y agoFunction calls are expensive if they are not optimized. However, the same is true for switch/case trees, and even for JIT'd code (dynamically created functions) ... In the Javascript world, "Your Mileage May Vary" truly is a motto.
- Igglyboo 12y agoWhy would the use a switch instead of a hashtable?
- kevingadd 12y agoGood compilers optimize a switch into a jump table, which is much, much faster than a hashtable. Using a hashtable for instruction dispatch in an emulator would be utterly insane. You'd use an array (but the compiler can do a better job by generating raw asm for a jump table.)
- Igglyboo 12y agoCould you explain why it would be insane? I was under the impression that all you needed was fast lookup time.
- kevingadd 12y agoA jump table is O(1). A hash table lookup is gonna be roughly O(N) for the hash + O(M) for the size of the hash bucket. Small hash tables can end up with very large buckets. Hash buckets are sometimes linked lists as well, so you pay the cost of that pointer indirection to walk the bucket. It's possible that a typical JS runtime can cache the hash value for a given string (especially literals), so that will help a bit for string keys. Integer keys might have a similar optimization. People overestimate the performance of hash tables. It's true that they are quite fast on a modern CPU, so you get away with using them extensively in dynamic languages like JS, but they are still way way slower than a jump table or directly accessing fields at statically known offsets.
- deleted 12y ago[deleted]
- tmzt 12y agoWould it make sense to use a bitwise test and two 128-part switch blocks?
- jwmerrill 12y agoThis used to be good advice, but I'm pretty sure that the modern engines all perform this optimization for you now.
- ricket 12y agoCan you elaborate? "pretty sure" sounds like a hunch rather than actual data.
- binarymax 12y agoI can't say for arguments, but optimizing for a changing array.length in-loop must be difficult if not impossible. for(var i=0;i<a.length;i++) if(check(a[i])) a.push('foo');
- mccr8 12y agoCompiler optimizations are never perfect. In this case, a compiler would just assume that push could be called and not hoist the length calculation.
- jkrems 12y agoJavaScript is complex enough that pretty much any code inside of the loop could end up doing an array push. Even `console.log(myCompletelyUnrelatedObject.x)` (given an evil property descriptor).
- mikeash 12y agoI don't know a whole lot about JIT compilers, but would it be possible to emit code with length optimized, and trap changes to it to fall back to a slow path in a way that wouldn't hurt the fast path? For example, you might mark the array so that when other code mutates it, that code also modifies the return address on the stack to point to some fixup code that puts you onto the slow path.
- Someone 12y ago