Is WebAssembly faster than JavaScript?

Most programs running on web sites are written in JavaScript. There are still a few Java applets and other plugins hanging around, but they are considered obsolete at this point.

While JavaScript is superbly fast, some people feel that we ought to do better. That’s where WebAssembly comes in. It is a binary (“pre-compiled”) format that is made to load quickly. It still needs to get compiled or interpreted, but, at least, you do not need to parse JavaScript source code.

The general idea is that you write your code in C, C++ or Rust, then you compile it to WebAssembly. In this manner, you can port existing C or C++ programs so that they run on Web pages. That’s obviously useful if you already have the C and C++ code, but less appealing if you are starting a new project from scratch. It is far easier to find JavaScript front-end developers in almost any industry, except maybe gaming.

I think it is almost surely going to be more labor intensive to program web applications using WebAssembly.

In any case, I like speed so I was interested so I asked a student of mine (M. Fall) to work on the problem. We picked small problems with hand-crafted code in C and JavaScript.

Here are the preliminary conclusions:

  1. In all cases we considered, the total WebAssembly files were larger than the corresponding JavaScript source code, even without taking into account that the JavaScript source code can be served in compressed form. This means that if you are on a slow network connection, JavaScript programs will start faster.

    The story may change if you build large projects. Moreover, we compared against human-written JavaScript, and not automatically generated JavaScript.

  2. Once the WebAssembly files are in the cache of the browser, they load faster than the corresponding JavaScript source code, but the difference is small. Thus if you are frequently using the same application, or if the web application resides on your machine, WebAssembly will start faster. However, the gain is small. One reason why the gain is small is that JavaScript loads and starts very quickly.
  3. WebAssembly (compiled with full optimization) is often slower than JavaScript during execution, and when WebAssembly is faster, the gain is small. Browser support is also problematic: while Firefox and Chrome have relatively fast WebAssembly execution (with Firefox being better), we found Microsoft Edge to be quite terrible. WebAssembly on Edge is really slow.

    Our preliminary results contradict several reports, so you should take them with a grain of salt. However, benchmarking is ridiculously hard especially when a language like JavaScript is involved. Thus anyone reporting systematically better results with WebAssembly should look into how well optimized the JavaScript really is.

While WebAssembly might be a compelling platform if you have a C++ game you need to port to the Web, I would bet good money that WebAssembly is not about to replace JavaScript for most tasks. Simply put, JavaScript is fast and convenient. It is going to be quite difficult to do better in the short run.

It is still deserving of attention since the uptake on WebAssembly has been fantastic. For online games, it has surely a bright future.

More content: WebAssembly and the Death of JavaScript (video) by Colin Eberhardt

Further reading: Egorov’s Maybe you don’t need Rust and WASM to speed up your JS; Haas et al., Bringing the Web up to Speed with WebAssembly; Herrera et al., WebAssembly and JavaScript Challenge: Numerical program performance using modern browser technologies and devices.

Published by

Daniel Lemire

A computer science professor at the Université du Québec (TELUQ).

28 thoughts on “Is WebAssembly faster than JavaScript?”

  1. Interesting results. JS optimisation has been a focus for browsers for many years of course, so there may be quite a bit of headroom to optimise webassembly to equal and exceed javascript performance in the long term

  2. You can be fairly certain that the main motivation is to increase code obfuscation… It’s probably harder to reverse engineering a WA program than an JS, even when obfuscated. So if you are Google, trying to protect your Gmail and maps sources, will you go for WA once it is widely supported?

  3. if you are on a slow network connection, JavaScript programs will start faster.

    This is not necessarily true, as WebAssembly can be compiled in batches, not to mention Mozilla have a tiered compiler in firefox which is capable of compiling and executing WebAssembly faster than it is downloaded.

    WebAssembly (compiled with full optimization) is slower than JavaScript during execution.

    Interesting blanket statement. I would very much like to see the data for this. Especially considering the fact that work has begun on replacing computationally-intensive nodejs packages written in JS with WebAssembly equivalents. How much of your benchmarking is affected by e.g. JS -> WASM interop? What kind of code are you comparing? Have you considered that WASM is still in MVP stages, and the different optimizations that multi-threading will bring?

    You seem to state that the only use-case here is gaming, but what about other computationally expensive applications, such as image editing programs, modelling programs, and the like?

    1. I am working on getting actual data that can be reported upon. My comments are preliminary.

      You seem to state that the only use-case here is gaming

      There are already image editing programs in JavaScript… heck you can write VR games in JavaScript.

      The angle I see for gaming is that lots of games are written in C++ or C# which makes WebAssembly compelling.

    2. Especially considering the fact that work has begun on replacing computationally-intensive nodejs packages written in JS with WebAssembly equivalents.

      Do we have examples yet where a highly optimized JavaScript implementation was beaten using WebAssembly? Something that went into production maybe?

  4. Keep in mind while perf testing that it’s a recognized problem that js is faster than web assembly when interacting with the DOM/js world. Improvements are being made in this area, but for now web assembly is best when most of the code calls more web assembly, with few entry and exit points.

  5. One thing to keep in mind when designing your tests is that the browsers haven’t optimized calls between JS, WASM and Native Code, yet. If your test is shuffling data between WASM and the DOM using native method calls, you may be measuring the context switch, and not code execution time, for example.

    See this October Mozilla Hacks article for more details.

  6. I would say that we have WASM because these questions were already asked and answered by it’s predecessor, Emscripten. Emscripten was a personal project by Alon Zakai, a developer at Mozilla. It got an early shot in the arm from the game community when Unity3D used it to replace their exising ActiveX control for previewing games on the web. It does this by recompiling your dot net assemplies using il2cpp, which is then compiled to WASM. The labor intensive part involves pushing a button and waiting.

    All c/cpp based projects are a pain to set up. So are web projects. All complex projects can be labor intensive. My tool chain compiles Vala to C to Wasm. The step from C to Wasm is not the hard part. I use VSCode with the CMake plugin, and I type Ctrl-B t build, and then F5 to launch my application in chrome. Or I can use the console to run it my desktop – either linux or windows 10.

    Wasm does not replace javascript. If you need a form to collect info and post it to a server, us conventional javascript. If I wanted to write a telephony app that runs in the browser, I’d pick Wasm. Use the right tool for the job – a great example (all the early stuff is game oriented) is Pico-8. It’s a toy 8bit graphpics game platform running on Lua. So to run on the web, they copiled Lua with Wasm, and run their Lua platform in the browser.

  7. Without methodology and/or data, you’re talking out of your ass. Without being able to repeat the tests, why should anyone trust your word, especially when there are repeatable tests showing opposite results?

    I’d recommend not publishing such claims until you’re ready to share details to back it up.

    1. you’re talking out of your ass

      Was this kind of rude language necessary to express your (otherwise healthy and sensible) skepticism?

      I provided preliminary conclusions, clearly labelling as such. I clearly indicate that there are contrary results and I provide several links.

      It is totally fair to criticize me for not providing evidence. However, read through the comments and you will notice that several commenters provide supporting evidence that WebAssembly is not (yet) a JavaScript killer.

    2. If you you’ve read any of Daniel’s past posts, you’d know that he always provides the code and data.

      This post is explicitly labeled “preliminary.” Patience.

      1. Thanks for pointing this out. The first that I heard of Daniel was when this blog was promoted on the Google News feed. On my phone, in the news app, Daniel’s credits and history don’t even show up. I assumed it was by yet another another trade journal pundit.

  8. I have no doubt that WebAsm is already faster for JavaScript in some scenarios, particularly those that leverage certain patterns that are slow in JavaScript (someone better in JavaScript can explain what those are: although the list has in some sense gotten smaller over time as the compilers have gotten better). That you didn’t find any such examples is interesting, although of course it depends on the details on what benchmarks were used!

    It also doesn’t surprise me there are benchmarks where JavaScript is faster: there has been an order of magnitude improvement in JavaScript performance over the last few years, and a couple of orders of magnitude if you go back further. An incredible amount of resources have been poured into the JavaScript JITs: the pace of development has been very fast compared to something like Java’s HotSpot.

    Now WebAsm is starting from a faster baseline, since some of the optimization is already done at compile time – but the WebAsm JIT and runtime is in the very early days, and no doubt has a ways to go.

    I don’t think WebAsm is positioned as a “replacement” for JavaScript, even by most of its proponents. It seems that its primary purpose is as a generic target for compilers, so you can write in any language and then compile it “for the web”. You could already do this with JavaScript, of course, but JS is far from an ideal target for this and the mismatch with many languages is large: it also distorts the design of languages that target JS in that they may compromise the user-facing language in order to cope with limitations of JS as an intermediate language. Woe unto anyone who tries to debug in the browser something written in a language that compiles to JS.

    So I think the more interesting question for the proposed uses of WebAsm would be whether it makes a better target for compilation, rather than whether a program written in C and compiled to WebAsm, is faster than a hand-written JS program (I do expect WebAsm to usually be faster even here – but maybe not yet).

  9. Your post is based on some fundamentally wrong assumptions.
    (And not only with JS being extremely slow and memory intensive even after multimillion investments into the JS JIT compilers. As an example, you can check the performance and the memory consumption of behemoths like Gmail, Facebook and Slack.)

    First of all, binary modules are not about size or the load time improvement. Moreover, until the very latest Chrome and Firefox builds loading WebAssembly modules was massively slower, then the JS code. The problem was with a single tier compilation for the WebAssembly, which had to optimize the application at once. Instead, binary modules are just a portable bytecode for the JS VM itself. This allows developers to execute the code written in the different programming languages inside the JS sandbox, thus solving the security issues with similar technologies from the past (like Flash, ActiveX etc). And despite your skepticism – there is a lot of code written for the front-end development as well as lots of developers using languages other than JS.

    The key feature of the WebAssembly is the predictability of performance. It is difficult to achieve it using the languages with GC and almost impossible with dynamically typed languages. Before the JS function gets JITed into an optimized set of the machine instructions, it has to be executed thousands of times with the exactly the same types of the input arguments. When this condition fails – function execution falls back to the interpreter.

    This behavior of JIT compilers makes it extremely hard to write the JS vs WebAssembly benchmarks. Usually, benchmark runs the same evaluation thousands of times and, as a result, easily gets to the fastest path. As a result, you are more or less benchmarking one compiler to another. On some platforms, notably on iOS, JS JIT works fantastic and easily beats the similar code, written in C and compiled using Clang to the WebAssembly. However, such benchmarks are not exploiting the weakest parts of the JS compiler and runtime at all and the real world result may be very well different.

    In our case, we have a rapidly evolving 500k LOC application, written in C++ (as we have to support clients with the very outdated hardware) which we used to compile to the Asm.js to provide a web version for the client with modern computers. Switching to WebAssembly gave us around 2x performance improvement, depending on the target browser and OS. The very similar results are shown by the Unity3D and Unreal Engines.

    To sum up – WebAssembly is best suited for the cases, where you have to process large amounts of data on the clients. Games and image editing seems to be the best fit at this moment of time. The official support of the WebAssembly by the Qt will push things forward as well.

  10. I can think of one scenario where WebAsm might make sense, and reduce code size: where some other language is used to write the front-end code, and transpiled into JavaScript.

    Java in particular creates large JavaScript files during transpiling (based on my experience with Google’s GWT, several years ago) and if instead of generating JavaScript the Java code can be compiled directly into WebAsm, I expect that sizeable gains can be made.

  11. The killer argument for WebAssembly for me is code sharing. We have heavy geometric code in our backends in our company and there is benefit to reuse some of these in the front ends, for example pose interpolation for trajectories.

    The story around c++ is weaker there, but rust offers a very easy way to compile pieces of your code to WebAssembly and reuse it in the front end. Speed is not a driving force for our work.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax