13 ms·
A first look at WebAssembly performance
- astrodust 10y agoThese performance numbers are amazingly impressive considering we're talking about JavaScript vs. C. Hopefully the various browser vendors can iron out some of the performance problems here and even things up better.
- batmansmk 10y agoOur benchmarks show amazing results... but not in speed. WebAssembly for us is about the size of the binary and the speed of parsing more than the speed of execution... A Javascript JIT with enough execution data can be even better than C in theory.
- richardwhiuk 10y agoYou could feed the profile data back into the C compiler in theory, so in practice, I think the C could always be faster.
- foota 10y agoIf you have dynamic data the best optimizations could change, and you can't feed the profile back to the compliler while the program is running. (Well... maybe in theory)
- flukus 10y agoThe JVM has been capable of this for a while. I think the overhead of profiling and applying optimizations has always been greater than any efficiency gains.
- foota 10y agoI think that's almost certainly false. JIT'd java is almost certainly faster than bytecode interpreted java. edit: or do you mean that the overhead of applying optimizations and profiling outweigh the performance gains relative to compiling from something like c directly to machine code?
- flukus 10y agoI mean the collection and application of the optimizations take up more CPU than the optimizations remove. This isn't JIT but real time optimizations (https://en.wikipedia.org/wiki/Adaptive_optimization https://en.wikipedia.org/wiki/Adaptive_optimization) while the system is running.
- zigzigzag 10y agoIt depends a lot on things like how long the program runs for, and whether you consider spare cores on the machine to be "taking up CPU" or not. Profile-guided optimisations win you about 20% in most industrial Java, apparently. So if you have a server that starts, warms up in say 30 seconds, and then runs for a week, you can see that it is easily profitable. For a command line app that lives for 500 msec, not so much.
- szemet 10y ago'the overhead of profiling and applying optimizations has always been greater than any efficiency gains.' Not necessarily, especially if you explicitly rely on them. For example in C++ you deliberately have to avoid overusing virtual functions if you don't want the overhead. In Java, virtual functions are the default, and you usually don't care: if you call them a lot (e.g. in a tight loop) JVM will adaptively give you the proper implementation - without per call indirection - or may even inline it. If you code C++ in Java style then JVM will win - so the overhead of (runtime) profiling and applying optimizations not always greater
- Vogtinator 10y agoG++ is able to optimize virtual calls to non-virtual calls in most cases (speculative devirtualization) by adding quick checks into the code (like if(obj->vtable == Class::vtable) Class:virtualMethod(obj);) which the JVM would do as well. So if G++ is able to tell the code paths leading to the virtual call, it does the same optimization as the JVM.
- pjmlp 10y agog++ cannot do that across dynamic libraries. It needs to see the source code at compile time. This is where JIT wins, as it can do that with binary deployed code.
- Sean1708 10y agoI've always wondered what C running on a JIT would be like. As far as I'm aware all the modern JIT languages are quite high level and do a lot more than C to begin with, so it would be interesting to see if you could eek out even more speed from C using a JIT.
- rl3 10y agoThis is called profile-guided optimization.[0] Slightly off-topic, but even Rust has it, courtesy of LLVM.[1] It doesn't seem very popular unfortunately. Most web/tech companies are obsessive about capturing user interaction data for UX purposes, but it would be nice if that data could be fed back into a profile-guided optimizer. In theory the compiled WebAssembly output would always be optimized for the latest usage trends, provided there were frequent builds. Depending on the product, it may even be possible to classify users into various high-level categories based on their behavior, and serve them a binary that's optimized for their specific use case. The latter's level of specificity probably wouldn't be worth it though. [0] https://en.wikipedia.org/wiki/Profile-guided_optimization https://en.wikipedia.org/wiki/Profile-guided_optimization [1] https://unhandledexpression.com/2016/04/14/using-llvm-pgo-in-rust/ https://unhandledexpression.com/2016/04/14/using-llvm-pgo-in...
- curyous 10y agoA JIT faster than C? I thought in theory it would always have to be slower because you have the overhead of the JITing. Also, isn't compiling C to native, the best you can hope for anyway? What could be faster than that, except for asm?
- tyoverby 10y agoTypical benchmarks for jitted languages like javascript don't include the jitting in their numbers. Jits can beat C in performance in situations where understanding how the program behaves at runtime influences code generation optimizations.
- emersonrsantos 10y agoHow the author turned off speedstep on a macbook? I assume he's using MacOS because of the Safari benchmark.
- ktta 10y agoHe does talk about the laptop he uses at the end of the post. >All tests were performed on a 2015 MacBook Pro, 2.5 GHz Intel Core i7, 16 GB 1600 MHz DDR3. For all tests the best of three runs was selected for the result.
- emersonrsantos 10y agoBut how do you disable CPU throttling on an intel macbook to do accurate benchmarks?
- krausest 10y agoI didn't. I believe that is's better to run a few times and take the best run. I payed for the turbo mode CPU and I'd like to know the performance on my machine. There's a lot going on my machine, and even more when a browser is running. The only thing (besides running on a clean machine) one can do about it is to measure multiple runs. Three runs are maybe a bit to little for scientific results, but I considered them good enough for a casual benchmark.
- igouy 10y agohttp://benchmarksgame.alioth.debian.org/for-programming-language-researchers.html http://benchmarksgame.alioth.debian.org/for-programming-lang... Those charts show 300 runs of Java n-body #3.
- simooooo 10y agoAm I the only one that was expecting web assembly to be like 10x JS speeds?
- benjismith 10y agoWell remember, WebAssembly just a different representation format for the same instruction set, executed by the underlying virtual machine (v8, spidermonkey, etc). So you should expect to see much of a performance difference. The main benefit of WebAssembly is so that we can write code using our favorite languages (not just javascript!) and compile to a common binary format the browser understands. The objectives of WebAssembly never had anything to do with performance.
- pmontra 10y agoAre there DOM bindings for languages other than JavaScript or is WebAssembly only for backend/webservices?
- Matthias247 10y agoAs far as I understand you can call JS APIs from WebAssembly, which means you use the already available DOM APIs. I don't know exactly what the calling convention from WASM to JS looks like, but I guess it's specified somewhere.
- TheCycoONE 10y agoThere are a few, none of them optimal for DOM manipulation yet because they all involve calling javascript. There is plans to add wasm dom hooks eventually. https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html https://kripken.github.io/emscripten-site/docs/porting/conne...
- vbezhenar 10y ago> The main benefit of WebAssembly is so that we can write code using our favorite languages JavaScript is already common format that browser understands and there are implementations for a lot of languages translating them to JavaScript. So WebAssembly definitely is about performance, because using other languages is already solved problem.
- strainer 10y agoI think there is no js version implemented which accesses the bodies parameters like this: x = body.x[body_index] I expect this should be much faster than accessing them like this: x = body.[body_index].x Because the latter requires pointer-from-property calculation for every single values access (which must be somehow optimised) The former just requires pointer-from-property calculation for every array (not element) involved in the nbody loops, the individual element|values are picked out by array addressing which is inherently much simpler than property access. I've used this method for nbody physics. I can modify a test to it and push to the repo.
- krausest 10y agoThat would be great. Just send me a pull request!
- strainer 10y agoWell I got it completing and its taking about 35% longer than the 'original' method. I do expect index lookups to be faster than property lookups so believe there must be some inefficiency in my hasty refactoring. Or there might be an issue with there being only 5 bodies in the test. Im a bit puzzled. Ill send the code later in the day.
- crocodileJS 10y agoYou must mean: x = bodies_x[body_index] versus x = bodies[body_index].x The "issue" with the nbody benchmark from the benchmarks game is that there's only four bodies, making this SOA-style approach have little payoff. It would be great if you could do such a test, but with a significantly larger amount of bodies.
- strainer 10y agoI do mean body.x[body_index], body.y[body_index], etc as: body={ x:[] ,y:[] ,z:[] ,vx:[] ,vy:[] ,vz:[] ,mass:[] } I find this is running 20% faster than the fastest on my chrome browser (an old version) but is slightly slower on firefox, but catches up a bit with 11 bodies. I expect it could run faster yet by crunching the code up more and maybe removing objects altogether, but i made few changes as possible just to compare the difference in addressing. There is also function "offsetMomentum" which tweaks the suns movement according to momentum of the planets, it seems very extraneous to me, gravitational influence should surely be sufficient in itself regarding conservation of momentum. I suspect that function is more likely a catch for large errors which can result from point grav bodies getting to close to each other.
- Derbasti 10y agoThe way I understand it, WebAssembly is all about the size of the binary and parsing overhead. Or, at a higher level, about enabling a level playing field between more languages than just JavaScript. Speed improvements from a common runtime and bytecode are certainly welcome, but if they are possible with WebAssembly, they are also be possible with plain JavaScript, and therefore shouldn't be visible in a comparison between the two. I, for one, hope that WebAssembly will enable, say, Lua as a first class citizen on the web.
- rnikhil275 10y agoLua is already on the web. Check out the Sailor MVC Framework.
- etiene 10y agoSailor author here. They probably mean on the front-end! :) For that we have Starlight (http://starlight.paulcuth.me.uk http://starlight.paulcuth.me.uk), which I use on Sailor as well. Very excited for the day we can run Lua natively on the browser!
- rnikhil275 10y agoYes. You are correct. I totally misunderstood the context.
- singularity2001 10y ago>> "but if they are possible with WebAssembly, they are also be possible with plain JavaScript" only with asm.js not with 'plain' JavaScript EDIT: sorry I completely missed the content of the OP! Wow
- crocodileJS 10y agoJavascript doesn't have the same type information as WASM, also it lacks a native 64-bit integer. The JIT can do some type inference to use integers internally in some cases, but it's not optimal. Predicting what sort of Javascript turns into what kind of native code on different JIT implementations is far from simple, too. Even if in theory, an equivalent result should be possible in some cases, it's unrealistic to expect that in practice.
- flohofwoe 10y agoThe C vs Firefox results are about the same that I'm seeing in my 8-bit emulator (http://floooh.github.io/virtualkc/ http://floooh.github.io/virtualkc/). For the Amstrad CPC (currently the most expensive system) on my 2.8GHz Core i5 MBP I'm seeing about 1.3 to 1.5 ms 'emulator time' per 16.6ms frame for the WASM/asm.js version on FF Nightly, and for the native version (clang -O3) about 1.2 to 1.4ms. This 'core emulator loop' is pretty much 100% integer code, with a lot of 8- and 16-bit integer bit operations (shifting, masking, ...). No calls into the browser or operating system, and almost no calls into the CRT or C++ stdlib (may be a small memcpy here and there). The performance differences for 'pure' C code between browser- and native-version are so small now that they are no longer relevant, at least for the use cases I encountered, or rather within the normal performance differences when running the code on a slightly different CPU. Calling out into HTML5 APIs is a whole different topic though ;)
- dreta 10y agoLanguages like Java and JavaScript don't let you lay data out in memory directly, nor do they give you much on control over how memory is accessed, so any performance benchmark involving C is entirely superficial. I can write 2 programs in C, both which iterate over some amount of elements and perform the same calculations on the same amount of data, and have one take 500ms and the other take 8s. It's all a matter of how you lay things out in memory.
- crocodileJS 10y agoYou actually can lay things out in memory using Typed Arrays. There's some overhead to reads/writes though (there is memory safety, after all).
- Klathmon 10y agoWhat's amazing is that in some engines, if the JIT can determine that you are within the bounds of the array, it can disable those checks for the duration of the loop. So something like for (x = 0; x < arr.length; x++) {...} can run at pretty much the same speed as C code.
- singularity2001 10y agoif you compare manually optimized JavaScript with manually optimized webassembly ( which was not available to the OP?), could you expect webassembly to be consistently faster than java on all browsers?
- matt4077 10y agoI'm surprised Chrome doesn't manage to be the fasted in any of these tests, considering the focus Google has put on performance and the resources I thought they were devoting to Chrome. It appears as if they'd come out ahead on average, but not by a definitive margin. Especially surprised by FF which I thought had somewhat dropped the ball (and/or simply been overrun once Google's business objectives aligned with the users' interests).
- icebraining 10y agoMozilla has done a great job of keeping up; they created some benchmarks to keep track of how well they're doing: https://arewefastyet.com/ https://arewefastyet.com/ https://areweslimyet.com/ https://areweslimyet.com/
- 13years 10y agoThere is a lot more to Chrome than just the JS engine. Much of Chrome's performance has been in areas that improve the total browsing experience.
- exabrial 10y agoI really want to like web assembly, but every time I read about it I SMH. We already have a bunch of great runtimes, compilers, and opcodes. I hate to see the effort duplicated yet again. Or maybe I'm missing something obvious?
- Ajedi32 10y ago> We already have a bunch of great runtimes, compilers, and opcodes. I'm confused. Are you suggesting we, for example, use the JVM for this instead? WASM is being designed specifically with the web in mind, and has a lot of design goals which just weren't a concern for other runtimes. See: http://webassembly.org/docs/high-level-goals/ http://webassembly.org/docs/high-level-goals/
- exabrial 10y agoWell not exactly, but I feel like the JVM, LLVM, parrot, CLR, or any one of those that have well defined opcodes could be leveraged instead of producing something entirely new. There's quite a bit of investment in those projects... Does that make more sense what I was trying to say?
- Ajedi32 10y agoThey actually have that question in their FAQ: https://github.com/WebAssembly/design/blob/master/FAQ.md#why-not-just-use-llvm-bitcode-as-a-binary-format https://github.com/WebAssembly/design/blob/master/FAQ.md#why...
- exabrial 10y agoI guess that particular case makes sense. Straight LLVM IR would probably be a security risk anyway unless they built a fairly solid verifier.
- n00b101 10y agoThe reason for not using LLVM bitcode or ASM.js is already covered in detail here https://github.com/WebAssembly/design/blob/master/FAQ.md https://github.com/WebAssembly/design/blob/master/FAQ.md I am unsure how JVM or CLR are relevant. WebAssembly is not a virtual machine byte code (and neither is LLVM, despite the name). As the name "WebAssembly" suggests, it is like an assembly language level target for "the web" (more precisely, for JavaScript interpreters found in web browsers). It is true that there is a lot of unfortunate duplication of effort and fracturing of technology happening here, due to historical legacy issues with web browsers. JVM and CLR are indeed highly mature and presumably secure VMs today. If we were to wave a magic wand and rewrite the history of the web browsers, perhaps it would be much better if JavaScript never existed and browsers used an off-the-shelf, standardized VM like JVM or CLR and we wrote web apps in C# or Java (or, at our discretion, F#, etc). This wouldn't solve the problem that WebAssembly is solving (i.e compiling native code, eg C++, for execution in the browser), but then maybe we wouldn't have needed that today if everyone (native and web) had standardized on a single VM target. But that's just not how things turned out, browsers created their own parallel technology stack from scratch so things like WebAssembly need to be created from scratch to work within the constraints that we are stuck with.
- DannyBee 10y agoJust wanted to say thanks for being so thorough in describing the compilation flags, versions, etc. It's really refreshing :) You also just may want to s/gcc/clang/, none of the gcc compile commands you are running are using gcc, they are all clang/llvm. Apple just aliased the gcc binary to clang on macs.