Confusion with how V8 turns function into hot function? [duplicate] - javascript

I was learning the inner workings of V8 and found out that there is JIT compiler which, on the fly, optimizes the hot functions with inline caching technique. I have only two questions, firstly, is function considered as hot function as long as it is executed repeatedly one after another several times? Secondly, after what exact number of repeated execution function gets hot in V8?

V8 developer here. Function "hotness" is not simply determined by the number of calls to it. Instead, V8 tries to predict how useful it would be to optimize a given function by estimating the amount of time spent executing the unoptimized version of that function. The exact heuristics of how this works, which other factors are taken into account (e.g. completeness/stability of type feedback), and the threshold when optimized compilation is triggered can and do change over time.
The reason is that optimized compilation is fairly expensive, so you'd only want to do it when it's likely to pay off. ("likely" because it depends in particular on how much work the function will do in the future, and predicting the future accurately is of course impossible, so there's always some amount of guesswork and heuristics involved.)

Related

TypeScript, why are subsequent function calls much faster than the original call? [duplicate]

I've got this problem I have been working on and found some interesting behavior. Basically, if I benchmark the same code multiple times in a row, the code execution gets significantly faster.
Here's the code:
http://codepen.io/kirkouimet/pen/xOXLPv?editors=0010
Here's a screenshot from Chrome:
Anybody know what's going on?
I'm checking performance with:
var benchmarkStartTimeInMilliseconds = performance.now();
...
var benchmarkEndTimeInMilliseconds = performance.now() - benchmarkStartTimeInMilliseconds;
Chrome's V8 optimizing compiler initially compiles your code without optimizations. If a certain part of your code is executed very often (e.g. a function or a loop body), V8 will replace it with an optimized version (so called "on-stack replacement").
According to https://wingolog.org/archives/2011/06/08/what-does-v8-do-with-that-loop:
V8 always compiles JavaScript to native code. The first time V8 sees a
piece of code, it compiles it quickly but without optimizing it. The
initial unoptimized code is fully general, handling all of the various
cases that one might see, and also includes some type-feedback code,
recording what types are being seen at various points in the
procedure.
At startup, V8 spawns off a profiling thread. If it notices that a
particular unoptimized procedure is hot, it collects the recorded type
feedback data for that procedure and uses it to compile an optimized
version of the procedure. The old unoptimized code is then replaced
with the new optimized code, and the process continues
Other modern JS engines identify such hotspots and optimize them as well, in a similar fashion.

About JavaScript compilation phase

As far as I know, JavaScript code goes through two phases: compilation phase and execution phase, when a JavaScript engine like V8 runs our code.
I wonder when the heap memory is actually allocated for a function.
More specifically, if I declare function and not call it in our code, does the JavaScript engine such as V8 still allocate memory for the function in the compilation phase?
Thank you
It's a bit more complicated than just two phases. Engines typically try to save memory when they can, but nothing is entirely free. It's safe to assume that a function that's never called consumes less memory than one that is called, but not zero.
In V8 in particular, (most) code is at first "pre-parsed". The preparser leaves behind some metadata about functions it has seen; mostly where in the source they start/end and some information about which variables from their outer context, if any, they'll need.
When program execution reaches a point where a function becomes available to JavaScript (as a variable), an actual object is created for it. This function object does not contain code or bytecode yet.
When a function is called, it is just-in-time compiled to bytecode. From this point on, memory is consumed for the bytecode.
If V8 notices that a lot of time is spent in the function, it may decide to generate optimized code for it. Optimized code is stored in addition to the bytecode, so the function's memory consumption grows again. Some functions never reach this point (e.g. when they're only called a few times).
Of course, when a function is executed, it can create other objects. (That's probably not what you're asking; just mentioning it for completeness.)

Why should I not not slice on the arguments object in javascript? [duplicate]

In the bluebird docs, they have this as an anti-pattern that stops optimization.. They call it argument leaking,
function leaksArguments2() {
var args = [].slice.call(arguments);
}
I do this all the time in Node.js. Is this really a problem. And, if so, why?
Assume only the latest version of Node.js.
Disclaimer: I am the author of the wiki page
It's a problem if the containing function is called a lot (being hot). Functions that leak arguments are not supported by the optimizing compiler (crankshaft).
Normally when a function is hot, it will be optimized. However if the function contains unsupported features like leaking arguments, being a hot function doesn't help and it will continue running slow generic code.
The performance of an optimized function compared to an unoptimized one is huge. For example consider a function that adds 3 doubles together: http://jsperf.com/213213213 21x difference.
What if it added 6 doubles together? 29x difference Generally the more code the function has, the more severe the punishment is for that function to run in unoptimized mode.
For node.js stuff like this in general is actually a huge problem due to the fact that any cpu time completely blocks the server. Just by optimizing the url parser that is included in node core (my module is 30x faster in node's own benchmarks), improves the requests per second of mysql-express from 70K rps to 100K rps in a benchmark that queries a database.
Good news is that node core is aware of this
Is this really a problem
For application code, no. For almost any module/library code, no. For a library such as bluebird that is intended to be used pervasively throughout an entire codebase, yes. If you did this in a very hot function in your application, then maybe yes.
I don't know the details but I trust the bluebird authors as credible that accessing arguments in the ways described in the docs causes v8 to refuse to optimize the function, and thus it's something that the bluebird authors consider worth using a build-time macro to get the optimized version.
Just keep in mind the latency numbers that gave rise to node in the first place. If your application does useful things like talking to a database or the filesystem, then I/O will be your bottleneck and optimizing/caching/parallelizing those will pay vastly higher dividends than v8-level in-memory micro-optimizations such as above.

JavaScript - What Level of Code Optimization can one expect?

So, I am fairly new to JavaScript coding, though not new to coding in general. When writing source code I generally have in mind the environment my code will run in (e.g. a virtual machine of some sort) - and with it the level of code optimization one can expect. (1)
In Java for example, I might write something like this,
Foo foo = FooFactory.getFoo(Bar.someStaticStuff("qux","gak",42);
blub.doSomethingImportantWithAFooObject(foo);
even if the foo object only used at this very location (thus introducing an needless variable declaration). Firstly it is my opinion that the code above is way better readable than the inlined version
blub.doSomethingImportantWithAFooObject(FooFactory.getFoo(Bar.someStaticStuff("qux","gak",42));
and secondly I know that Java compiler code optimization will take care of this anyway, i.e. the actual Java VM code will end up being inlined - so performance wise, there is no diffence between the two. (2)
Now to my actual Question:
What Level of Code Optimization can I expect in JavaScript in general?
I assume this depends on the JavaScript engine - but as my code will end up running in many different browsers lets just assume the worst and look at the worst case. Can I expect a moderate level of code optimization? What are some cases I still have to worry about?
(1) I do realize that finding good/the best algorithms and writing well organized code is more important and has a bigger impact on performance than a bit of code optimization. But that would be a different question.
(2) Now, I realize that the actual difference were there no optimization is small. But that is beside the point. There are easily features which are optimized quite efficiently, I was just kind of too lazy to write one down. Just imagine the above snippet inside a for loop which is called 100'000 times.
Don't expect much on the optimization, there won't be
the tail-recursive optimization,
loop unfolding,
inline function
etc
As javascript on client is not designed to do heavy CPU work, the optimization won't make a huge difference.
There are some guidelines for writing hi-performance javascript code, most are minor and technics, like:
Not use certain functions like eval(), arguments.callee and etc, which will prevent the js engine from generating hi-performance code.
Use native features over hand writing ones, like don't write your own containers, json parser etc.
Use local variable instead of global ones.
Never use for-each loop for array.
Use parseInt() rather than Math.floor.
AND stay away from jQuery.
All these technics are more like experience things, and may have some reasonable explanations behind. So you will have to spend some time search around or try jsPerf to help you decide which approach is better.
When you release the code, use closure compiler to take care of dead-branch and unnecessary-variable things, which will not boost up your performance a lot, but will make your code smaller.
Generally speaking, the final performance is highly depending on how well your code organized, how carefully your algorithm designed rather than how the optimizer performed.
Take your example above (by assuming FooFactory.getFoo() and Bar.someStaticStuff("qux","gak",42) is always returning the same result, and Bar, FooFactory are stateless, that someStaticStuff() and getFoo() won't change anything.)
for (int i = 0; i < 10000000; i++)
blub.doSomethingImportantWithAFooObject(
FooFactory.getFoo(Bar.someStaticStuff("qux","gak",42));
Even the g++ with -O3 flag can't make that code faster, for compiler can't tell if Bar and FooFactory are stateless or not. So these kind of code should be avoided in any language.
You are right, the level of optimization is different from JS VM to VM. But! there is a way of working around that. There are several tools that will optimize/minimize your code for you. One of the most popular ones is by Google. It's called the Closure-Compiler. You can try out the web-version and there is a cmd-line version for build-script etc. Besides that there is not much I would try about optimization, because after all Javascript is sort of fast enough.
In general, I would posit that unless you're playing really dirty with your code (leaving all your vars at global scope, creating a lot of DOM objects, making expensive AJAX calls to non-optimal datasources, etc.), the real trick with optimizing performance will be in managing all the other things you're loading in at run-time.
Loading dozens on dozens of images, or animating huge background images, and pulling in large numbers of scripts and css files can all have much greater impact on performance than even moderately-complex Javascript that is written well.
That said, a quick Google search turns up several sources on Javascript performance optimization:
http://www.developer.nokia.com/Community/Wiki/JavaScript_Performance_Best_Practices
http://www.nczonline.net/blog/2009/02/03/speed-up-your-javascript-part-4/
http://mir.aculo.us/2010/08/17/when-does-javascript-trigger-reflows-and-rendering/
As two of those links point out, the most expensive operations in a browser are reflows (where the browser has to redraw the interface due to DOM manipulation), so that's where you're going to want to be the most cautious in terms of performance. Some of that can be alleviated by being smart about what you're modifying on the fly (for example, it's less expensive to apply a class than modify inline styles ad hoc,) so separating your concerns (style from data) will be really important.
Making only the modifications you have to, in order to get the job done, (ie. rather than doing the "HULK SMASH (DOM)!" method of replacing entire chunks of pages with AJAX calls to screen-scraping remote sources, instead calling for JSON data to update only the minimum number of elements needed) and other common-sense approaches will get you a lot farther than hours of minor tweaking of a for-loop (though, again, common sense will get you pretty far, there, too).
Good luck!

Recursive function calling in JavaScript

I know you should tread lightly when making recursive calls to functions in JavaScript because your second call could be up to 10 times slower.
Eloquent JavaScript states:
There is one important problem: In most JavaScript implementations, this second version is about 10 times slow than the first one. In JavaScript, running a simple loop is a lot cheaper than calling a function multiple times.
John Resig even says this is a problem in this post.
My question is: Why is it so inefficient to use recursion? Is it just the way a particular engine is built? Will we ever see a time in JavaScript where this isn't the case?
Function calls are just more expensive than a simple loop due to all the overhead of changing the stack and setting up a new context and so on. In order for recursion to be very efficient, a language has to support some form of tail-call elimination, which basically means transforming certain kinds of recursive functions into loops. Functional languages like OCaml, Haskell and Scheme do this, but no JavaScript implementation I'm aware of does so (it would only be marginally useful unless they all did, so maybe we have a dining philosophers problem).
This is just a way the particular JS engines the browsers use are built, yes. Without tail call elimination, you have to create a new stack frame every time you recurse, whereas with a loop it's just setting the program counter back to the start of it. Scheme, for example, has this as part of the language specification, so you can use recursion in this manner without worrying about performance.
https://bugzilla.mozilla.org/show_bug.cgi?id=445363 indicates progress being made in Firefox (and Brendan Eich speaks in here about it possibly being made a part of the ECMAScript spec), but I don't think any of the current browsers have this implemented quite yet.

Categories