Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Javascript Eval is slower, when it shouldn't be

So i'm trying to create my own JS framework just for my own pleasure (and probably then convert into usefullness) and I most of the time focus on generating JS dynamicly (since having higher level with JS as language-in-the-middle is bad idea, IMO)

And I got into one trouble. I was trying to do following

var f = null;
var converted = "f = function(){ <do something here>";
for(var x in list)
 converted+=list[x];
converted+="};";
eval(converted);

So this pretty much writes constructed function to f, that I can later execute.

But here's the catch - it runs slower, than if I just write code of f completely in file, which is very strange. Let me explain why it's strange to me: when you just run eval each time, Chrome precompiler (or whatever browser precompiler - chrome is what I target) can't cache-compile the code, because it expects, that it will change with each run.

However, when you save this to a function, it creates a new VM machine file, because after you saved the function's code, you can't change it. So why, when I do such eval, it runs slower than normal execution? I mean after code was executed more than once. Why this should matter?

PS: The method I had shown above, works faster that eval-ing each time. So I don't understand why stopwatches show time inbetween, again, ignoring first 1-10 calls

PPS: Test case: http://jsperf.com/evaluated-function-vs-real-function/2

like image 697
Andrew Yukhymchak Avatar asked Oct 20 '25 03:10

Andrew Yukhymchak


1 Answers

eval is basically unoptimizable because the compiler doesn't know what it's doing. Even if you save it into a function, the compiler has to opt out a lot of optimizations, because changing your code in a certain way might break the eval function.

This is why, usually, when you need to do an eval, you do it in another function : that way, the compiler can be sure you didn't modify local scope in the eval, and optimizes a lot better.

JS VMs are really a lot about heuristics. They try to guess what you want to do, and optimize for the general case. eval (or new Function) prevent them to do a lot of that.

Function.new might be a little faster, because the compiler will know it won't try to modify the scope.


ALSO ! Note that eval might act a little differently than what you're used to. For example, eval('a') and (0, eval)('a') are not the same :

I'll demonstrate it with this

window.a = 5;
void function () {
  var a = 1;
  eval('a = 2');
  console.log(a);
  console.log(window.a);
}();

This will print 1 then 5

window.a = 5;
void function () {
  var a = 1;
  (0,eval)('a = 2'); // <- this line has changed
  console.log(a);
  console.log(window.a);
}();

Whereas, this will print 1 then 2.

You can also read this : Global eval, what are the options.

like image 62
Ven Avatar answered Oct 21 '25 18:10

Ven



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!