63

I am confused about JavaScript engines right now. I know that V8 was a big deal because it compiled JavaScript to native code.

Then I started reading about Mozilla SpiderMonkey, which from what I understand is written in C and can compile JavaScript. So how is this different from V8 and if this is true, why does Firefox not do this?

Finally, does Rhino literally compile the JavaScript to Java byte code so you would get all the speed advantages of Java? If not, why do people not run V8 when writing scripts on their desktops?

Gordon Gustafson
  • 36,457
  • 23
  • 109
  • 151
Jan
  • 639
  • 1
  • 6
  • 3
  • 1
    Rhino can compile to Java byte code. https://developer.mozilla.org/en/Rhino_JavaScript_Compiler – Thilo Jan 26 '10 at 03:16

4 Answers4

87

There are various approaches to JavaScript execution, even when doing JIT. V8 and Nitro (formerly known as SquirrelFish Extreme) choose to do a whole-method JIT, meaning that they compile all JavaScript code down to native instructions when they encounter script, and then simply execute that as if it was compiled C code. SpiderMonkey uses a "tracing" JIT instead, which first compiles the script to bytecode and interprets it, but monitors the execution, looking for "hot spots" such as loops. When it detects one, it then compiles just that hot path to machine code and executes that in the future.

Both approaches have upsides and downsides. Whole-method JIT ensures that all JavaScript that is executed will be compiled and run as machine code and not interpreted, which in general should be faster. However, depending on the implementation it may mean that the engine spends time compiling code that will never be executed, or may only be executed once, and is not performance critical. In addition, this compiled code must be stored in memory, so this can lead to higher memory usage.

The tracing JIT as implemented in SpiderMonkey can produce extremely specialized code compared to a whole-method JIT, since it has already executed the code and can speculate on the types of variables (such as treating the index variable in a for loop as a native integer), where a whole-method JIT would have to treat the variable as an object because JavaScript is untyped and the type could change (SpiderMonkey will simply "fall off" trace if the assumption fails, and return to interpreting bytecode). However, SpiderMonkey's tracing JIT currently does not work efficiently on code with many branches, as the traces are optimized for single paths of execution. In addition, there's some overhead involved in monitoring execution before deciding to compile a trace, and then switching execution to that trace. Also, if the tracer makes an assumption that is later violated (such as a variable changing type), the cost of falling off trace and switching back to interpreting is likely to be higher than with a whole-method JIT.

Ted Mielczarek
  • 3,617
  • 23
  • 30
  • 16
    Note that in the intervening years Firefox has switched to using a whole-method JIT as well "JaegerMonkey" and dropped the tracing JIT. – Ted Mielczarek Aug 08 '12 at 13:41
16

V8 is the fastest, because it compiles all JS to machine code.

SpiderMonkey (what FF uses) is fast too, but compiles to an intermediate byte-code, not machine code. That's the major difference with V8. EDIT- Newer Firefox releases come with a newer variant of SpideMonkey; TraceMonkey. TraceMonkey does JIT compilation of critical parts, and maybe other smart optimizations.

Rhino compiles Javascript into Java classes, thus allowing you to basically write "Java" applications in Javascript. Rhino is also used as a way to interpret JS in the backend and manipulate it, and have complete code understanding, such as reflection. This is used for example by the YUI Compressor.

The reason why Rhino is used instead of V8 all over the place is probably because V8 is relatively new, so a lot of projects have already been using Rhino/Spidermonkey as their JS engine, for example Yahoo widgets. (I assume that's what you're referring to with "scripts on their desktops")

edit- This link might also give some insight of why SpiderMonkey is so widely adopted. Which Javascript engine would you embed in your application?

Community
  • 1
  • 1
adamJLev
  • 12,986
  • 11
  • 57
  • 62
  • 2
    Umm TraceMonkey also does JIT translation to machine code ... Also I don't think it's accurate at all to say that V8 "compiles" JavaScript to machine code - it's more or less the same sort of JIT approach as TraceMonkey. – Pointy Jan 26 '10 at 04:10
  • @Pointy, The difference AFAIK between TraceMonkey and V8 is that TraceMonkey compiles to intermediate code, some of which gets JIT compiled to machine code as it executes. V8 compiles everything directly to machine code. – Matthew Crumley Jan 26 '10 at 04:39
  • 1
    "V8 compiles JavaScript source code directly into machine code when it is first executed. There are no intermediate byte codes, no interpreter." Source: http://code.google.com/apis/v8/design.html So basically compilation like a C compiler would do. Also, V8 compiles all JS, and TraceMonkey does JIT – adamJLev Jan 26 '10 at 04:56
5

If you want to see how the various in-browser Javascript engines stack up, install Safari 4 (yes it runs on Windows now too!), Chrome V8, Firefox 3.5, and IE 8 (if you are on windows) and run the benchmark:

http://www2.webkit.org/perf/sunspider-0.9/sunspider.html

I believe as Pointy said above, the new Firefox 3.5 uses TraceMonkey that also compiles to intermedit code on the fly using some form of JIT. So it should compare to V8 somewhat favorably. At least it won't be 10x slower than V8 like Firefox 3 SpiderMonkey (without JIT) was.

For me... safari 4.0.3 was 2.5x faster than Tracemonky in Firefox 3.5.3 on Win XP. IE8 was much much slower. I don't have Chrome installed at the moment.

Don't know about Rhino compiling to java bytecode. If it's still interpreting the dynamic features of Javascript such as being able to add attributes to object instances at runtime (example obj.someNewAttribute="someValue" which is allowed in Javascript)... I'm not so sure that it's entirely "compiled" to bytecode, and you might not get any better performance other than you don't have to compile from Javascript source code text every time your Javascript runs. Remember that Javascript allows very dynamic syntax such as eval("x=10;y=20;z=x*y"); which means you can build up strings of code that get compiled at runtime. That's why I'd think Rhino would be mixed-mode interpreted/compiled even if you did compile to JVM bytecode.

The JVM is still an interpreter, albeit a very good one with JIT support. So I like to think of Rhino-on-JVM as 2 interpreter layers (interpreter-on-interpreter) or interpreter^2. Whereas most of your other Javascript engines are written in C, and as such should perform more like interpreter^1. Each interpreter layer can add 5-10x performance degradation as compared to C or C++ (ref Perl or Python or Ruby for example), but with JIT the performance hit can be much lower on the order of 2-4x. And the JVM has one of the most robust & mature JIT engines ever.

So your mileage will definitely vary and you probably would benefit from doing some serious benchmarks if you want a real answer for your intended application on your own hardware & OS.

Rhino can't be too awfully slow, since I know lots of folks are using it. I think it's main appeal is not its speed, but the fact that is easy-to-code/light-weight/embeddable/interpreter that has hooks into Java libraries, which makes it perfect for scripting/configuration/extensibility of your software project. Some text editors like UltraEdit are even embedding Javascript as an alternative macro scripting engine. Every programmer seems to be able to stumble through javascript pretty easily, so it's easy to pick up as well.

One advantage to Rhino is that it runs pretty much anywhere the JVM runs. In my experience, trying to get stand-alone TraceMonkey or SpiderMonkey to build & run from command line can be a bit painful on systems like Windows. And embedding in your own application can be even more time consuming. But the payback to having an embeddable language would be worth it for a big project, as compared to having to "roll your own" mini scripting solution if that's what you're looking to do.

Scripting with Rhino is really easy if you have Java and the rhino jar, you just write your javascript and run it from command line. I use it all the time for simple tasks.

linguanerd
  • 681
  • 3
  • 11
  • I installed chrome 4 on my XP machine, and it runs the sunspider benchmarks about 3x faster than Firefox 3.5.3 Tracemonkey. Also discovered that V8 is pleasantly easy to download and build compared to my previous experience with SpiderMonkey. Of course you need svn + python 2.4 + scons 1.0.0 + Visual Studio 2005/2008 (VC++ 2008 free edition supposedly works too) all of which I already had running on my developer PC. To be fair, maybe I'll go back and try TraceMonkey build again and see how it stacks up nowadays. – linguanerd Jan 26 '10 at 13:24
  • 3
    Note that Sunspider isn't the only answer, it's just one JavaScript benchmark (albeit one that JavaScript engine authors have optimized heavily for). – Ted Mielczarek Jan 27 '10 at 13:58
  • VC++ 2008 express(free) does work for compiling v8 with scons, did it earlier this week. – Fire Crow May 19 '10 at 21:09
3

To respond the question, why native code Vs Byte code...

The native code is faster and for google a strategic choice because they have plan to JS one of them at least is ChromeOS.

A good video about this question is posted on Channel9 with an interview with Lars Bak the man behind V8 can be found here

Zied
  • 1,596
  • 11
  • 19