5 ms·
Can you elaborate on what's wrong with the final solution from the article? I don't see anything wrong there and I wouldn't expect your snippet to be faster.
by robryk 13y ago
Can you elaborate on what's wrong with the final solution from the article? I don't see anything wrong there and I wouldn't expect your snippet to be faster.
- goldenkey 13y agoChecking the index in every iteration of a loop will effectively double the amount of operations performed in every iteration of the loop for this scenario. That is, O(2n) versus O(n)
- inglor 13y agoNot really, things like branch prediction and JIT optimizations will kick in pretty fast. This is why these benchmarks on jsperf suck - the code gets a different 'fresh' version every time and jits (like crankshaft in v8 ) don't get to work. Effectively, you're checking 'the performance of interperted JavaScript' most the the time.
- goldenkey 13y agoI bet my bottom dollar that branch prediction is not going to magic away that index dependent if statement in a language like JS, even with Crankshaft in full effect.
- inglor 13y agoHere, it's within 20% of the performance. Definitely not n vs 2n http://jsperf.com/oh-look-branches http://jsperf.com/oh-look-branches
- Dylan16807 13y agoBut the code is actually doing a whole bunch of things, let's say 20, with each loop. So it's O(21n) vs. O(20n). 2n implies looping twice or something, not a single extra operation. (and 20 is probably a gross underestimate if we're comparing console.log to a mere ==)
- goldenkey 13y agoI made an assumption, you're making an assumption too. I'd agree that in any case where it would actually matters, you'd be doing a small amount of ops in the if statement. The complexity change will depend on what you were doing in the loop as compared to the speed of a single if statement. If it were a large amount of ops, then yes, it'd be a more minor difference.
- Dylan16807 13y agoMy point is that "O(2n)" is an extremely specific and misleading way to characterize 'extra conditional per iteration'. It doesn't matter what the actual percentage difference is.
- deleted 13y ago[deleted]
- goldenkey 13y agoI agree, now what is the correct notation so we all can learn? :-)
- Dylan16807 13y agoIt's completely pointless to use such a notation here in lieu of description or benchmarks, but if you insist then use something like O(kn) vs. O((k+1)n)
- robryk 13y agoI've expected the JS interpreter to optimize that out. Turns out I was wrong and the version from the article is even 40% slower for a loop that iterates over 5000 elements and does a trivial amount of work: http://jsperf.com/for-loop-vs-for-in-loop/18 http://jsperf.com/for-loop-vs-for-in-loop/18
- inglor 13y agoYou're not giving the JIT a chance to warm up at all. Also, you're degrading into 'slow mode' because your array has different types. Basically, it looks like you're doing a lot of bad things to the JIT on purpose :P Both the different types and the delete (array with holes) are _very_ harmful for performance in v8.
- goldenkey 13y agoThe arrays with holes are called Sparse Arrays, I googled for 'sparse array v8 performance' and didn't find much, but I've previously seen a Google Presentation on a slide-sharing site that did mention how poor sparse arrays perform when compared to normal contiguous arrays.
- underwater 13y agoThat's not how big O notation works. You need to eliminate constant multipliers because you can't make any assumptions about the amount of work each iteration involves. It certainly doesn't correlate directly to machine instructions.
- inglor 13y agoSpeed isn't the only issue here. In fact, the execution of the looping construct itself is almost meaningless compared to what you're actually doing in it. (Explained here http://stackoverflow.com/a/17253577/1348195 http://stackoverflow.com/a/17253577/1348195 ) JSPerf is a horrible place to benchmark these things, see http://mrale.ph/blog/2012/12/15/microbenchmarks-fairy-tale.html http://mrale.ph/blog/2012/12/15/microbenchmarks-fairy-tale.h... and http://mrale.ph/blog/2013/08/14/hidden-classes-vs-jsperf.html http://mrale.ph/blog/2013/08/14/hidden-classes-vs-jsperf.htm... by Vyacheslav Egorov (worked on v8) For example: if(array.length > 0) doFunction(array[0]); array.slice(1).forEach(doOtherFunction); Is far more readable and maintainable than that mess with the useless indexes and does the same thing. Optimizing based on microbenchmarks and not checking for deopts and doing profiling is worthless.
- goldenkey 13y agoIt's not worthless when you are writing an app that happens to run in the browser. I agree 1000-fold that the Array manipulation techniques are extremely easy to read. Keep in mind though, you are creating a new copy of the [1-n]array through the slicing, and the overhead of the function call with forEach will matter on large Arrays. Really depends what you are building. Don't call performance optimization worthless.
- inglor 13y ago"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%." - Knuth Micro benchmarks are not how we optimize - we profile.
- Eiwatah4 13y agoWho says the function call actually happens? If the function is short enough, they are a very good candidates for the JIT to inline. If they aren't short, the overhead of calling the function shouldn't matter much anymore.