In Chrome, JavaScript runs on the V8 Engine, but what is the engine that runs WebAssembly code?
How is the browser suddenly able to give improved performance with WebAssembly? Is this WebAssembly engine always available in browser, or has it been added to browsers recently?
WebAssembly is only supported by all major browser (Chrome, Firefox, Safari, Edge) since Nov/2017, meaning WebAssembly is not supported by older version of browsers. (blog post from mozilla)
To understand why WebAssembly is faster then Javascript there is a excellent series by Lin Clark (link).
The conclusion from the article is quote
WebAssembly is faster than JavaScript in many cases because:
fetching WebAssembly takes less time because it is more compact than JavaScript, even when compressed.
decoding WebAssembly takes less time than parsing JavaScript.
compiling and optimizing takes less time because WebAssembly is closer to machine code than JavaScript and already has gone through optimization on the server side.
reoptimizing doesn’t need to happen because WebAssembly has types and other information built in, so the JS engine doesn’t need to speculate when it optimizes the way it does with JavaScript.
executing often takes less time because there are fewer compiler tricks and gotchas that the developer needs to know to write consistently performant code, plus WebAssembly’s set of instructions are more ideal for machines.
garbage collection is not required since the memory is managed manually.
WebAssembly is a new web standard instruction set that is executed by the browser. Within Chrome WebAssembly runs within V8 https://v8project.blogspot.com/2016/03/experimental-support-for-webassembly.html?m=1
There are many runtimes for WebAssembly such as the browser (V8, SpyderMonkey, JavaScriptCore).
Also, there are runtimes which implement the WASI such as:
Wasmtime which uses Cranelift and in turn, LLVM
WAVM which uses LLVM
Wasm3 which is an interpreter in wasm
GraalVM WASM which uses a JVM implementation and then LLVM
Lunatic which uses WasmTime and native bindings
and more
WebAssembly can run on many runtimes and so in turn, it can operate on many machines and vms
Related
I'm just getting started with Node.js and I have quite a bit of background in Python and C++. I got to know that Node.js is a runtime environment but I'm having a rough time understanding what actually it does to a code that makes it different from a compiler. It would be better if someone can explain how specifically runtime environments differ from typical compilers and interpreters.
Let's take it this way:
Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
V8 is the Google Javascript engine, the same engine is used by Google Chrome.
There are other JS engines like SpiderMonkey used by Firefox, JavaScriptCore used by Safari, and Edge was originally based on Chakra but it has been rebuilt to use the V8 engine.
We must understand the relationship first before moving to how the V8 works.
JavaScript engine is independent of the browser in which it's hosted. This key feature enabled the rise of Node.js. V8 was chosen to be the engine that powered Node.js.
Since V8 is independent and open-source, we can embed it into our C++ programs, and Nodejs itself is just a program written in C++. Nodejs took the V8 and enhanced it by adding features that a server needs.
JavaScript is generally considered an interpreted language, but modern JavaScript engines no longer just interpret JavaScript, they compile it.
Since you have a C++ background, C++ performs what is called ahead-of-time (AOT) compilation, the code is transformed during compilation into machine code before the execution.
JavaScript on the other side is internally compiled by V8 with just-in-time (JIT) compilation is done during execution. While the code is being executed by the interpreter it will keep track of functions that are called very often and mark them as hot functions then it will compile them to machine code and store them.
A compiler is a program that converts code from one language to another. In Java for example we have a the java compiler javac that you can run on your .java files to compile your code into platform independent java file (can be understood and executed by any jvm).
Since you are new to JavaScript, you will encounter the transpilers (like babel) that turns your next generation JavaScript code into a legacy JavaScript code that can be handled by all browsers (even old ones).
A runtime is a more vague concept. It can go from being a set of functions to run a compiled code on a specefic operating system to being the whole environment in which your program runs.
For the case NodeJS, it's the environment on which you can run a JavaScript program out of the browser. It took the V8 Engine of Chrome that runs JavaScript on the Chrome browser and made it available everywhere. That's how JavaScript moved from being a Client side Programming Language that runs only on the browser to a server side Programming Language that can run on servers equiped with the runtime environment NodeJS.
A few simple points that might help:
C/C++ code will be compiled by the C/C++ compiler into the machine code and will not need any runtime environment to run (mostly, except the run-time libraries)
Python code needs Python interpreter to execute it. As you say you have background in C++/Pythons you must be familiar with all these nitty-gritty
JavaScript was meant to run in the browser and it does mostly, however some smart folks thought of running it outside the browsers and they created the JavaScript execution engine (which is kind of stand alone JavaScript executor) and Node.js is just one of them. It simply runs the JavaScript code outside browser on it's own. The execution is still interpretation of JavaScript code so it is just an interpreter with hell lot of support functions for managing the runtime dependencies, package management, etc.
In Node.js website, they say Node.js is a JavaScript runtime.
Are web browsers like Chrome, Firefox, Edge, ... JavaScript runtimes?
I thought of course, web browser is JS runtime. But I'm confused, In this video 12:10~ He says Web browser is not just JavaScript runtime because it can do more things
at one time, it can give us other things.
But I think V8 engine only can do one thing at one time, while JS runtime can do more things than one at one time.
Am I wrong?
A browser contains a Javascript engine (for example Chrome v8). The engine implements a Javascript runtime, which includes the call stack, heap and event loop. The browser also usually includes a set of APIs that augment the Javascript runtime and make asynchronous code execution possible.
NodeJS also implements a Javascript runtime using Chrome's v8 engine as well as the Libuv library (event loop and worker threads).
Here's a good video that breaks this all down:
https://www.youtube.com/watch?v=4xsvn6VUTwQ
They are right, a JavaScript runtime just executes the JavaScript code.
All Web browsers include a JavaScript runtime engine(RE) that executes js code for them but they also have other plugins like java or flash, as well as an html/dom parser and renderers that are not part of the RE, even if those modules were written in JavaScript it does not mean they would be part of the RE.
Does one enable the other, or does one affect the other?
It seems V8 lets native C++ access Javascript, and NaCl lets you run native code in the browser.
Sorry for the naive question. I'm behind on recent developments in Javascript, was surprised that modern browsers actually JIT-compile all!
Short answer- No.
Longer answer,
Chrome ships with the V8 JS engine and uses it to execute JavaScript embedded in web pages. V8 in Chrome cannot be extended to access C++ or vice versa.
NaCl is a toolchain and runtime environment allowing you to compile your existing C++ code into a safe executable and then execute it securely from a web page.
V8 can be used on its own by embedding it inside your own C++ application, extending it as you see fit.
HTH,
John
http://research.google.com/pubs/archive/37204.pdf
It is possible to run (a modified version of) v8 inside NaCl. The code sequences emitted by the JIT must conform to the sandbox safety rules.
It is unlikely to be possible to do the converse.
:-)
-bsy
I can't find information on the web how W3C languages compile to machine code. I know that the gap between the web and the processor must be somehow the browser, but how does it work and what are the steps till Javascript is executed in the processor?
Links to scientific documents would be also greatly appreciated.
It's up to the implementation; the specification is the full description of the language and how it's supposed to work, implementations are free to satisfy that implementation in any way they like. Some implementations seem (from the outside) to run it purely as an interpreter in the old sense; others may or may not compile to bytecode; V8 (the JavaScript engine in Chrome, Chromium, Brave, Node.js, and others) used to compile to machine code (twice, for hotspots in the app), but now starts out parsing to bytecode and running it in an interpreter and only compiling hotspots as necessary (details). (There's also a V8 mode where it only interprets, which they're experimenting with for environments where compiling at runtime isn't an option, such as iOS where non-Apple apps aren't allowed to allocate executable memory.)
The V8 team (V8 being the JavaScript engine in Chromium and Chrome) periodically publish descriptions of how they get the fantastic speed out of V8 that they do. You may find some of that on the V8 blog.
Naturally, you can also kick around the code of any of the open-source implementations. V8 and SpiderMonkey (Mozilla's engine) are the two major open-source ones I know.
This may help : http://www.ecma-international.org/publications/standards/Ecma-262.htm
There is no spec for how to translate into bytecode (That is up to the browser developers) but there are specs about how the language should behave
For Firefox there's some specifications on its bytecodes:
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Bytecodes
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/Bytecode
For V8 it's compiled to native code directly:
http://jayconrod.com/posts/51/a-tour-of-v8-full-compiler
Javascript (as it's name suggests) is a dynamic scripting language. Meaning that it's code is analysed and executed at runtime by the web-browser's Javascript engine.
It is up to the Web-browser, how it wants to deal with Javascript. Some may generate an intermediate language, or bytecode. Some may directly analyse and execute it.
Here are the steps to the simplest way to execute Javascript (parsing and executing at runtime):
Parsing and Preprocessing (recursive descent or otherwise)
Analysis
Execution
Chrome's Javascript Engine compiles Javascript to native platform-specific machine code (for optimum performance) It also has a Garbage Collection Mechanism.
In addition to the useful, specific answers already given, the phrase 'adaptive optimisation' is probably worth looking up if performance is your main interest. JavaScript and its interpreters are just the latest instance of systems that need to convert something else to machine code at runtime, so there's plenty of wider reading. The bytecode forms of Pascal, Smalltalk, Java, etc can easily enough be viewed as an intermediate form in the process of running a defined language on arbitrary hardware — Apple's SquirrelFish explicitly creates a bytecode and uses a JIT compiler on that, for example.
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?
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.
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?
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.
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
2022 Update
V8 as also SpiderMonkey do support MultiPass Compilation as also SinglePass Compilation.
Java Rhino got deprecated and replaced by a new concept called Truffle Framework it is part of the GraalVM Stack which is in fact a JVMCI added to the JVM where CI means Compiler Interface. That allows the Truffle Language Implementer Framework to Implement any Language and translate that to Java Byte Code in MultiPass and Single Pass. the ECMAScript implementation is called GraalJS and it comes in 2 Flavors
GraalJS the 1:1 Rhino Replacement including compatability mode for incremental adoption and graal-node a NodeJS Fork where v8 is replaced with the GraalJS Engine.
as sayed Truffle is a Polyglot Language Implementer Framework so that works with any GraalVM Supported Language.
hope that helps and makes some sense since the jar versions do most best work when the whole stack has aligned versions you should alaways install the complet stack:
https://github.com/graalvm/graalvm-ce-builds/releases
download and install that then use the so called gu command to add graaljs
follow the instructions here: https://github.com/oracle/graaljs
Yes GraalVM can in general Compile Single Binary Executeable Files of all Polyglot Languages this is called AOT Compilation it has faster boot times but less throughput it can also do JIT and it can do a mix of both.