10 ms·
Replacing JavaScript Hot Path with WebAssembly
- Roboprog 8y agoToo bad no wasm on IE 11 Where it would be needed most
- tracker1 8y agoDepends on your use case... a lot of places are just plain deprecating IE altogether.
- ghayes 8y agoIsn't Microsoft one of the founding companies in the initiative? [0] [0] https://webassembly.org/ https://webassembly.org/
- simlevesque 8y agoMicrosoft !== IE The logo on the front page you linked it the logo of Microsoft's other browser, Edge. There is no other mention of Microsoft or Internet Explorer on it.
- Roboprog 8y agoAs well they should:-) But IE 11 has been given a stay of execution until 2025 I believe. And sadly most of my users are still on it (government and healthcare)
- iamleppert 8y agoDid you see the benchmarks? There's almost no difference between javascript and wasm except for a single certain browser. So you're really going to take on the maintenance burden to get that better performance? This is a cool technique but I can just imagine the looks on my team mates faces when I tell them it isn't react... :/
- nicoburns 8y agoWeird that they didn't say which browser is which :/
- RivieraKid 8y agoProbably were worried it would look like they're trying to shame their business partners (Apple and Microsoft I guess).
- acqq 8y agoActually it seems that the second worst in JavaScript (when executing their example) is Chrome? User robko here https://news.ycombinator.com/item?id=19167078 https://news.ycombinator.com/item?id=19167078 measured the code on node.js, and node.js is based on Chrome's V8 and he measured 1.5 sec vs article author's of around 2.7s, so it would seem that robko has some almost twice as fast CPU, and the other two (fast) JavaScripts are under 500 ms, and the slowest is 8 seconds, so V8 of Chrome remains the only candidate for the second worst performing of their example.
- om2 8y agoI wish they had at east posted a browser-runnable version of their test so we could see for ourselves which browser is which, or compare JS vs WASM on our own systems. (On this type of code, I'd expect Safari to be the fastest, not Chrome.)
- acqq 8y agoSee my "minimal" C++ translation in my other post here. There's not much to add. For JavaScript start with their code, but add the allocation, just replace allocations with var a = new Uint32Array(height * width); and b the same. Add the timing (1), put in HTML and you're done. It's easy, just a few minutes for anybody who works with that (and this site should be filled with the competent developers AFAIK). 1) https://developer.mozilla.org/en-US/docs/Web/API/Performance https://developer.mozilla.org/en-US/docs/Web/API/Performance
- PhilippGille 8y agoI would have loved to see Go included in the comparison as well. It can compile to wasm since 1.11.
- dassurma 8y agoGo was pretty much a non-starter. They (currently) need a runtime which will make the file size non-competitive to the other ones. Also, since only Chrome has support for threads in WebAssembly (in Canary), we’d not be able to make any use of the concurrency.
- asien 8y agoThe performance gain are so small , its not worth this setup overhead . The average user won’t see the difference. Hence , the simplicity of’this module . Just do it in JS , chrome as 70% market share why would you ever bother ? V8 has received decades of optimizations and it can easily compete with compiled languages in terms of speed. I was hyped to death for WASM , but this is the tenth article I’m reading on this subject and I still ending on the same conclusion : there is no advantage for front end developers to use WASM. Only Rendering Engine ( Unity , Adobe Products, Autodesk ) can really benefits from this.
- writepub 8y agoThe article sets out to prove the predictability of WASM's performance, and not necessarily a performance gain wrt js. > This confirms what we laid out at the start: WebAssembly gives you predictable performance. No matter which language we choose, the variance between browsers and languages is minimal If you're not hyped about WASM, it's probably because your app and customer base's browser preferences are on the js engine's JIT happy-path, which could hold true for most apps. There could very easily be a js path that is significantly worse in performance on chrome, just saying, 70% market share is both a blessing and a curse. Another major reason for WASM hype is for C#, Rust, C, C++, Go devs to reach parity with js in terms of web accessibility. Frameworks like Blazor (from MSFT) have taken all the best practices & advantages of React and made them available to C# devs.
- pjmlp 8y ago> have taken all the best practices & advantages of React and made them available to C# devs. The irony is that C# devs were the first to use reactive programming before React even existed.
- news_to_me 8y ago> chrome [h]as 70% market share why would you ever bother ? This view seriously needs to die. It's honestly not that hard to test in two or three browsers, and the differences are minor enough that it isn't a pain. But the only way that's possible is through Web standardization, which only happens when there are diverse options. As web developers, it's our duty to keep the web healthy, and that means not only optimizing for a single browser.
- gok 8y agoWow all these numbers seem insanely bad. 500 milliseconds to transpose 16 million pixels (so 64mil bytes)? A modern CPU should able to do that at least 10x faster, if not 100x.
- robko 8y agoYou are correct. The code is using an inefficient cache access pattern, so most of the time is spent waiting. You probably won't get 100x faster without SIMD, but 10x is certainly doable. Unfortunately, SIMD.js support has been removed from Chrome and Firefox a while ago, even though it is not available in wasm to this day.
- kllrnohj 8y agoHow would SIMD do anything to address the problem's fundamental anti-cache-friendly access patterns? You'd need to restructure the problem to be cache-friendly, but SIMD won't really be relevant to that.
- robko 8y agoYou can use both at once. Usually, you'd have something like 64x64 tiles in cache and use 4x4 or 8x8 tiles for SIMD.
- kllrnohj 8y agoThey are bad but not way off for that basic for loop, depending on which rotation is being applied. Using their code on my Intel-based workstation at around 3ghz using GCC 7.3 it takes around 80-100ms to rotate a 4096x4096 buffer 90 or 270, and 14ms to rotate 180. Max memory bandwidth of something like an i9-9900k is 41.2GB/s. This test reads & writes 128mib of data. So max theoretical achievable performance here is around 3-4ms. Max theoretical. So 100x is not really feasible. 10x, though, very much is, as the quick convert shows a peak time of 14ms with a 180* rotation. Of course the major source of slowness here is that the reads/writes are not sequential, and the 90 & 270 rotations are achieving a fraction of the possible bandwidth they could as the input reads are jumping around, so every single one is a cache miss and the other 60 bytes in each cache line on the miss will be purged before it's used again. Flipping it would mean the writes are never utilizing a full cache line, either, though. So you can't really "fix" that, not easily at least. So either your read or write bandwidth ends up tanking and you can only achieve roughly 6% of the max (only ever using 4 bytes of the 64-byte cache line) for that half of the problem. Without some clever magic to handle this your max theoretical on a 41.2GB/s CPU drops to around 50ms. All that said it's clear that WASM is very far off from native levels of performance. ~5x slower isn't something to brag about. But hey maybe the test system was a potato, and the 500ms isn't as bad as it sounds.
- robko 8y agoMy guess is that the JS implementation of the worst-performing browser is having trouble with the non-1 for-loop steps. Doing 90-degree image rotation with fixed steps and some index calculations should work better (0.18 sec vs 1.5 sec for their implementation in node.js): for (var y = 0; y < height; y++) for (var x = 0; x < width; x++) b[x + y*width] = a[y + (width - 1 - x)*height]; Although that's still far from the theoretical maximum throughput because the cache utilization is really bad. If you apply loop tiling, it should be even faster. This problem is closely related to matrix transpose, so there is a great deal of research you can build upon. EDIT: 0.07 seconds with loop tiling: for (var y0 = 0; y0 < height; y0 += 64){ for (var x0 = 0; x0 < width; x0 += 64){ for (var y = y0; y < y0 + 64; y++){ for (var x = x0; x < x0 + 64; x++){ b[x + y*width] = a[y + (width - 1 - x)*height];
- seanwilson 8y agoMaybe this is what you meant but the snippet can be optimised a ton as well unless I'm missing something: - Move the "y * width" calculation outside of the "for x" loop. - The multiply operators can be replaced with addition e.g. replace "y * width" with "counter += width" each y iteration and similarly for the x loop. Optimising inner loops is really fun. How much of the speed up in the article is because the JS engine can't figure out how to optimise it compared to the WebAssembly compiler?
- robko 8y agoI tried a few micro-optimizations, but they did not make a measurable difference, so I kept the code short instead. But maybe some JIT is particularly bad at loop hoisting, so it might make a difference there.
- tom_mellior 8y agoThese code motion/strength reduction optimizations are standard even in mildly optimizing compilers. I would be very surprised if an optimizing JavaScript compiler did not perform them automatically.
- 8y ago
- thefounder 8y agoCan we expect a day when WASM will be first class citizen in browsers (i.e like JavaScript) and not just a sidekick?
- tachyonbeam 8y agoNot anytime soon IMO because WASM still has to access browser APIs through the DOM, which is really built with JS in mind.
- goatlover 8y agoWhy not anytime soon? VBScript and Dart where given the ability to access the DOM in IE and Chrome in the past.
- markdog12 8y agoIt's coming: https://github.com/WebAssembly/host-bindings/blob/master/proposals/host-bindings/Overview.md https://github.com/WebAssembly/host-bindings/blob/master/pro...
- int_19h 8y agoHTML DOM is described in terms of IDL interfaces, complete with types. I wouldn't say that it's optimized for JS - indeed, that's why jQuery and similar were introduced. When WHATWG took over, they improved it specifically for better JS interop, but it's still straightforward to map to most statically typed languages. https://dom.spec.whatwg.org/#infrastructure https://dom.spec.whatwg.org/#infrastructure https://heycam.github.io/webidl/ https://heycam.github.io/webidl/
- olliej 8y agoThe problem isn’t exposing the APIs, the problem is the wasm has what is essentially the C memory model, so you couldn’t trust any point/object you get from wasm land. That’s why there so much work being put into giving wasm a more typical (for a vm) typed heap. Similar issues occur with lifetime of objects - if you get anything from the dom, you have to keep it live if wasm references it, but wasm has no idea of what memory or a handle is. These are solvable problems, but you’re not getting dom access until after they’re solved.
- kodablah 8y agoI'd be tempted to hand-write the WAT for that. It's not that bad, much easier than dropping into a x86 asm block in C or something.
- dassurma 8y agoI did :D Turns out compilers are pretty good at generating WAT.
- z3t4 8y agoI would try optimizing the JS before dropping down to webassembly. For example try replacing let and const with var as let and const in loops have to create a new variable for each iteration.
- Etheryte 8y agoThat's not how let and const work at all, where did you get that impression?
- z3t4 8y agoHave you ever made a for loop using var only to have the variable point to the last value in the iteration ? And had to make a closure using forEach, function or self calling function ? With let you do not have to do that as a new variable is created for each iteration. Instead or reassigned when you use var.
- revskill 8y agoThis industry, and Google specifically, instead of improving Javascript, Node and Deno, focus on a weird land. We use JS because we don't want to touch much on those C, C++ things. No, keep going forward with JS, keep innovate with JS instead of going backward with C.
- alangpierce 8y agoThe "predictable performance" point applies not just to performance across browsers but also that you don't need to pay JIT warm-up costs. A while back, I ran some benchmarks on the same codebase in TypeScript and AssemblyScript and found that wasm was much faster than JS for short computations and often slower than JS when V8 is given multiple seconds to fully warm up the JIT: https://github.com/alangpierce/sucrase/issues/216 https://github.com/alangpierce/sucrase/issues/216 So really, it depends a lot on the use case. In my case, it's often a short-lived node process that a user is directly waiting on, so compiling to wasm is probably useful. It also depends on what you're doing; some types of work (e.g. where you'd want careful memory management) are a lot harder for V8 to optimize from JS and can be expressed more nicely in AssemblyScript or another language that gives more memory flexibility.
- why_only_15 8y agoFor that, it looks like unless you're running the same js on a really huge dataset webassembly will win (going from the second speed test). Even when you're compiling 50MB of JS with that thing, Wasm is 5% slower than JS, and when you're compiling 500KB (more typical) it's 300% faster.
- gcb0 8y ago(overly ironic) tl;dr "let's rewrite something in this new browser feature because the other browser feature we added last week is not supported anywhere and buggy in chrome"
- jijji 8y agoanyone like to take a guess what "Browser 4" is?
- barrystaes 8y agoHmm.. the Google article stipulates: > WebAssembly on the other hand is built entirely around raw execution speed. So if we want fast, predictable performance across browsers for code like this, WebAssembly can help. So i wanted to see how i could use WebAssembly in a React webapps. I found this SO question sees the opposite: > When running this [ WebAssembly] code in Chrome, I observe "pauses" that cause the app to be a bit jittery. Running the app in Firefox is a lot faster and smoother. https://stackoverflow.com/questions/53584607/react-app-with-webassembly-is-slow-in-chrome-but-fast-in-firefox-why https://stackoverflow.com/questions/53584607/react-app-with-... Same code, different browser, different performance. I'd love seeing a Google Developer answering that question in depth..
- IshKebab 8y agoThat looks like a bug, rather than an inherent characteristic of wasm.
- sisu2019 8y agoWebAssembly is a bit underwhelming to be honest. It feels like every week there is a new language that can come close to C performance meanwhile they've been working on WebAssembly for years and years and it can barely beat JS. Shouldn't WA as a greenfield project with it's extremely basic memory model and lack of runtime or standard library be super easy to optimize? After all, there is no point in having the bad ergonomics of assembly together with the awful performance of JS, right?
- amelius 8y agoThose are runtimes in the second range. Are they doing that in a separate thread or do they block the UI? And how long does it take to transfer the data to that thread?
- deleted 8y ago[deleted]