20 ms·
Is WebAssembly magic performance pixie dust?
- staticelf 6y agoI work on an application that could benefit from web assembly but the biggest hurdle for me is that it's kind of complex. The web used to be quite simple but now it sometimes feels like you have to have a very large team in order to do anything. Sure, I could probably do web assembly but that would take time from other things that also is important. I get that it is very useful for larger teams making larger applications like Figma. But for small teams it feels like the tooling isn't there yet to do anything useful in the timespan that I need to. That being said, assemblyscript seems very interesting and I probably should look into it.
- enos_feedler 6y agoI agree. Is there something specific that you found difficult that should be simple?
- root_axis 6y agoIt's not that complex, anything in computers can seem complex if you're not familiar with it. I would suggest that you're just not familiar with it, and that's not a knock against you, it's just something that you need to study like anything else. It's not true that you need a large team to do anything on the web these days, the same technology works today that has worked for the last two decades, but if you want to leverage the benefits of new technology you need to invest the time to understand how it works, that's just the nature of technological advancement.
- rudi-c 6y agoParent mentioned the lack of tooling, and that is indeed where most of the cost of using WebAssembly lies. You don’t really need to learn the assembly language itself since you’ll probably just be calling emcc. However, you may need to build code to marshall more than just ints and strings to the JS code. Even after you do, you’ll run into the classical issues of keeping track of object references across a GC & non-GC system. You may need debugging and find that in-browser debuggers for WASM are primitive/non-existent. You may need to figure out how unmangle stack traces —- including mixed JS/WASM traces. Third-party tools like Sentry for error reporting may not have built support (they sort of recently have and is very under-documented). All solvable problems, but it’s a lot of time spent not building the product. There are plenty of good uses cases but it’s usually not the ones based on the false premise that native is somehow always better than interpreted.
- jillesvangurp 6y agoIt looks complex until you sit down and do it and force yourself to understand what you are doing. Most things are like that. The way I structure learning things like this in my team is by organizing spikes. We commit to diving into some technology with the goal of finding out how feasible it is for us to use it and a secondary goal of maybe getting something useful going. However the primary goal is finding out if it can work and if so exactly how. If it works out it becomes a regular thing we work on and integrate. This usually starts with studying what is there, what the risks and benefits are, etc. At some point you reach the point where the only way to learn more is simply doing it. You can analyze something to death without fully understanding it. Just sitting down and doing it becomes the logical next step. The payoff is usually non linear: you gain more if it works than you lose if it doesn't. This is one of those things that you might suspect is valuable like that. So your job is finding that out in an efficient way. In your team, I would task one or two of your people with spending a max of 2 days to validate that they can take a simple bit of typescript, convert it to assembly script, compile it and hook it up. Chances are pretty good that they'll have working code at the end of those two days. Worst case you lose two days. Best case you figure out it's easy and just works and you move forward.
- fergie 6y agoWhy does TypeScript use javascript as a compile target and not web assembly?
- kevingadd 6y agoTS predates WASM by years and WASM is also not adequate for executing TS.
- aikah 6y agoBecause Typescript was designed to be a tool to write Javascript with type annotations at first place and nothing else.
- FlyingSnake 6y agoCan TS be compiled directly to WASM? I don't think WASM and JS are 1:1 compatible, but I'm out of my depth here.
- Schampu 6y agoAssemblyScript initially targeted TS->WASM compilation, by only supporting a strict subset of the TS language. But at some point they dropped that idea and defined their own TS-like language. I don't know the reason for this, but my guess is that TS is too dynamic to just directly compile it to WASM?
- pjmlp 6y agoMicrosoft has done exactly the same on their MakeCode IoT compiler, using TypeScript and Python. "MakeCode Languages: Blocks, Static TypeScript and Static Python" https://makecode.com/language https://makecode.com/language It is very hard to generate good AOT code when dealing with dynamic languages, of any kind.
- deleted 6y ago[deleted]
- 6y ago
- kevingadd 6y agoOne important thing to note that this post kind of hints at: JavaScript can be optimized more than equivalent WebAssembly if you give the JS runtime enough help, because it can use runtime-only information to produce better-optimized JS. It can exploit type information gathered during runtime to devirtualize method calls and produce type-specialized code, while also doing things like escape analysis to eliminate some allocations entirely. You have to carefully identify places in your native code where you can do unchecked array accesses, etc, but the JS runtime just figures it out for you. For any of those optimizations to happen for your WASM code, the compiler has to be able to do it statically and that can be much harder. Devirtualization in particular is essential for Java or C# to run fast and some C++ codebases also benefit tremendously from it. If you're interacting a lot with JS APIs from WASM (like issuing network requests or creating DOM elements, etc) you're going to be dealing with lots of dynamically typed data, and in those scenarios handwritten JS may actually be faster than WASM because the runtime can JIT optimal code with the right type specializations. Note that these optimizations will fail if you aren't careful about how you write your JS: If a given function f(x,y) is passed values of different types during execution, it probably won't be fully optimized. If you have two functions f1(x,y) and f2(x,y) and ensure that each one is only passed values of a certain type, they will both be heavily optimized (iirc the JS runtime terminology for these functions is 'monomorphic') Naturally, this means uses of Function.apply and Function.call should be avoided at all costs.
- RcouF1uZ4gsC 6y agoI have seen much the same made about Java versus C++ for the past 25 years that the Java byte code JIT would have more information and thus be able to optimize and do stuff like devirtualization better. However, that has not planned out. There are a few reasons for this. First C++ and Rust optimizers can do amazing things when they are given time. In addition, I think devirtualization is not as big a deal in C++ and Rust because in general you avoid writing code that uses virtual functions when you are writing performance sensitive code and instead use things like templates/generics where there is no indirect function calls.
- kevingadd 6y ago
- tpetry 6y agoSo AssemblyScript can beat JavaScript if you benchmark every function and then optimize them by hand every time it is slower? So most (all?) of the code posted which looked like a straight port to AssemblyScript was slower than JavaScript before optimizing it? I don‘t know how you feel, but i personally don‘t want to optimize every function to get the promised speed :(
- onion2k 6y agoIf your app is doing most of the work it needs to do in 1ms, but one path takes 200ms, then clearly you only need to optimize things on the slow path. You don't have to optimize everything to get a huge perf improvement.
- hackcasual 6y agoAssemblyScript is still in development, if you're interested in WASM optimizing an app, Rust or C are better bets
- deleted 6y ago[deleted]
- moonchild 6y agoSee also: ‘Not So Fast: Analyzing the Performance of WebAssembly vs. Native Code’ - https://www.usenix.org/system/files/atc19-jangda.pdf https://www.usenix.org/system/files/atc19-jangda.pdf
- justin66 6y agoTwo years old. I bet the "actionable guidance for future optimization efforts" they provide has been acted upon.
- vanderZwan 6y agoI'm sure it's being acted upon, but these kinds of developments take time so I'm not sure if it has "landed" yet.
- daninet 6y agoStill, you can archive significant speed-ups with WebAssembly at some use cases. For example, I have a hash function library (https://github.com/Daninet/hash-wasm https://github.com/Daninet/hash-wasm) where I was able to archive 14x speedup at SHA-1 and 5x speedup at MD5 compared to the best JS implementations. You can run the benchmarks on your computer here: https://daninet.github.io/hash-wasm-benchmark/ https://daninet.github.io/hash-wasm-benchmark/
- hackcasual 6y agoA large part of that would be better support for integer math, and 64 bit in particular for sha1
- CodesInChaos 6y agoWhy are 64-bit integers useful for SHA-1 which uses 32-bit words?
- vnorilo 6y agoThe full product of 32-bit multiply is 64-bit.
- CodesInChaos 6y agoI don't think SHA-1 uses any multiplications, only bitwise operations (not, and, or, xor), addition and rotation.
- Cthulhu_ 6y agoThat's exactly the kind of thing I think WASM is good at - small, computationally expensive libraries that are easy to just plug in. I'm more of a web developer and every time I think "hmm, could I use this to build a webapp?", but quickly shrug it off because it would create a big headache and the JS execution is rarely the bottleneck (and if it is, it's likely developer error and inefficiencies than the language / interpreter).
- jokoon 6y agoI really wish python could be compiled to WASM. I tried brython, and it's very very slow.
- 0-_-0 6y agoFWIW, Nim can be compiled to WASM.
- francisl 6y agoyes but it mostly undocumented, unsupported and trouble assured. I tried several time and always got stuck somewhere. Rust that has the reputation to be hard, but is way simpler and faster to get into WebAssembly. I wish they adopt nlvm as the default compiler, it would make stuff like that way easier and probably boost adoption.
- deleted 6y ago[deleted]
- dom96 6y agoSomeone has to come in and make it supported. Adopting nlvm isn't going to magically make it easier. The reason it's easier in Rust is because someone that's passionate about WASM came along and did the work up front to document everything and make it as simple to compile to WASM as possible, the same is certainly possible in Nim, just need someone to put in some work :)
- francisl 6y agoYes, you're 100% right and I hear you. I really do like Nim, but suggesting it to do WebAssembly out of the box could be deceiving and do no good. The project is currently in the hard spot where it's hard to convince your team of using it, but because its hard they is less contribution. As for llvm, you might be right, I'm not an expert in that particular field. But it seems there is a lot of already backed in stuff you'll have for free. Like Wasm, debugging, optimization. We'll see how the Crystal project manage to get Wasm and how llvm will help them.
- hackcasual 6y agoAssemblyScript lacking support for closures really hampers it, since so many typescript code patterns leverage them.
- TekMol 6y agoFor me, the showstopper regarding WebAssembly is that browsers do not support a textual version that I can just throw in where I want to hand optimize a function. If I could just replace my slowest Javascript function with handcrafted WebAssembly code, that would be great. But having to dabble with external compilers and splitting my code into multiple files is too much of a burden.
- candiodari 6y agoShouldn't be too hard to make a library that would allow this. Would you be interested in that ? So let's say something like the following example, would you use it? This should be possible: <script src="some.url/gopherjs.js"> <script type="application/golang"> package main import "fmt" func main() { fmt.Printf("yeah baby\n") // Effectively console.log } </script> Obviously this would take more than a bit of time to start up (seconds), but the idea is of course that you don't do this once you deploy to production, and replace by inline webassembly.
- TekMol 6y agoI would surely try it out! What is "inline webassembly"?
- candiodari 6y agoWebAssembly.instantiate(new Uint8Array([0,97,115,109,1,0,0,0,....], { type: 'application/wasm' }); Inline webassembly = directly specifying the wasm binary inside of the html or javascript file.
- kevingadd 6y agoYou can pretty easily just ship a 1kb .wasm module and load it and export a function from it to call from JS. Of course, then all your data needs to live in wasm-accessible memory, and you can't use strings or objects anymore...
- maga 6y agoA few years ago I did similar comparison but in context of Node.js and sans manual optimizations: https://github.com/zandaqo/iswasmfast https://github.com/zandaqo/iswasmfast In my work, I have come to conclusion that it seldom pays off to go "native" when working with Node.js. More often than not, rewriting some computationally heavy code in C and sticking it as a native module yielded marginally better results when compared with properly optimized js code. Though, that doesn't negate other advantages of using said technologies: predictable performance from the start and re-using existing code base.
- RcouF1uZ4gsC 6y agoLooking at the C++ code, it seems like you could use std::push_heap/pop_heap to implement your binary heap. The code would be simpler, and there is a chance it could be faster since a lot of the standard library algorithms are very heavily optimized.
- toastal 6y agoWhat about performance for SpiderMonkey and JavaScriptCore? I’m a little disappointed that everything in the article from a V8-only perspective. Is it too late to want a future where V8+Blink aren’t de facto? edit: Just saw > Web Advocate @Google.
- self 6y ago> I’m a little disappointed that everything in the article from a V8-only perspective. The advantage of using v8 (d8) here is that the author could benchmark different optimization strategies. I don't think jsc lets you do that.
- lovasoa 6y agoThere was a project zero article on HN recently [1] that said that bound check eliminations were removed from v8 because they allowed attackers to easily turn a type confusion into a memory read-write primitive: > As a result, last year the V8 team issued a hardening patch designed to prevent attackers from abusing bounds check elimination. Instead of removing the checks, the compiler started marking them as “aborting” But this post, which also appears to be written by someone from google with access to v8 developers, states that : > You never go out of bounds. This means TurboFan does not need to emit bounds checks [...] Does someone here know more about bound checks eliminations in TurboFan ? Are they removed in some cases but not others ? [1] https://googleprojectzero.blogspot.com/2021/01/in-wild-series-chrome-infinity-bug.html https://googleprojectzero.blogspot.com/2021/01/in-wild-serie...
- saagarjha 6y agoThis ensures aborting bounds checks to some parts of the the pipeline, but this doesn't mean that later optimizations can't determine that the check is dead code and remove it. For example: https://doar-e.github.io/blog/2019/05/09/circumventing-chromes-hardening-of-typer-bugs/ https://doar-e.github.io/blog/2019/05/09/circumventing-chrom...
- debt93 6y agoHonestly, the fact that AssemblyScript's Array implementation does not double the internal capacity but instead adds just one more slot when reallocating makes me worry about the quality of the language as a whole. I hope it is just an oversight, but come on...
- kohlerm 6y agoAlso without an integrated GC, most modern languages do not run well on ASM.
- kohlerm 6y agoI meant WASM of course :-)
- gvb 6y agoDoubling the allocation is a "hack" that is helpful when reallocations are common and thus is helpful for languages that extend arrays very often (typical of dynamic languages with GC) and where memory is cheap and plentiful. One of the prime features of assembly language is that the person (compiler) that is generating it expects tight control over what it does. A 2*X allocation when you ask for X is unexpected. Imagine if, when you went to the ATM and withdrew $100, the bank actually withdrew $200 from your account and held back the extra $100 so that, the next time you went to the bank and withdrew $20 it would take it out of the "held back" amount rather than doing another withdraw. I would be very unhappy with that algorithm.
- debt93 6y agoIt is not a "hack". It is the behavior that I expect from a dynamically resizable array. std::vector in C++ does it, so does Vec in Rust, and they are not dynamic languages with GC.
- pjmlp 6y agoWhich std::vector though? ISO C++ places no such requirement on std::vector, each implementation is free to choose their own implementation provided it matches the O() notation requirements. C++ is not like Rust where the implementation dictates the semantics.
- isaacimagine 6y ago~lol, imagine not doubling the capacity of a dynamic array upon allocation.~ In all seriousness, this is a great read, and I was mildly surprised JS was about the same speed as Wasm once TurboFan kicks in. As a compiler engineer, it's nice step back and appreciate the myriad of runtime-based optimizations that can be done with modern JIT compilers. That being said, assembly script doesn't perform and high-level optimizations upon compilation, so I wonder how fast it will be once fully matured.
- kevingadd 6y agoThe correct growth rate is typically not actually 2x, but it's certainly not +1 either :)
- RicardoLuis0 6y agogrowth rate varies between use cases, too small and you pay on performance overhead, too large and you pay on memory overhead, 2x is a decent mid-spot
- masklinn 6y agoWasn’t there some consideration that with 2x you could never reuse previous contiguous allocations but at 1.4 (ish?) it was an option and improved fragmentation in some cases? Of course it depends on the behaviour and binning (or lack thereof) of your allocator. Edit: it’s 1.5, any growth factor below 2 has this property, how far below 2 regulates how quickly it happens, https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#motivation https://github.com/facebook/folly/blob/master/folly/docs/FBV... > it can be mathematically proven that a growth factor of 2 is rigorously the worst possible because it never allows the vector to reuse any of its previously-allocated memory. > [...] > choosing 1.5 as the factor allows memory reuse after 4 reallocations; 1.45 allows memory reuse after 3 reallocations; and 1.3 allows reuse after only 2 reallocations
- dahfizz 6y agoI'm not sure I understand the benefit of this. With a growth factor < 2, you have a chance of getting back chunks of memory that were previously used. That doesn't affect fragmentation / cache hits since all your data is always in the current chunk. What am I missing?
- not_knuth 6y agoJust you wait until Lars Bak [0] gets hired by some company to make a fast WebAssembly runtime. Until that happens I won't take any performance comparisons of WASM vs. X seriously :). [0] https://en.wikipedia.org/wiki/Lars_Bak_(computer_programmer) https://en.wikipedia.org/wiki/Lars_Bak_(computer_programmer)
- NohatCoder 6y agoI really think WebAssembly missed the target. What we really needed was a language doing away with the dynamic nature of JavaScript, while adding 64 bit integers and generic SIMD instructions, and keeping high level features like strings and automatic memory management. Instead we got the most bare-bone language imaginable, making everyone have to reinvent the wheel for everything. That is not actually fast. If WebAssembly had stuff like basic string manipulation, browsers could easily map that directly to efficient implementations. But with the current rules everything has to be provided as basic instructions that must be compiled under much stricter security rules. WebAssembly is not assembly, it is an intermediate representation shared between two compilers, and it is actually pretty bad at that.
- saagarjha 6y agoI mean, it's a virtual machine like the JVM. It's just that the code is already generally run through an optimizer, while Java bytecode typically isn't.
- NohatCoder 6y agoYeah, that is a way to look at it. My point isn't what we call it exactly, my point is that it is a hack job that is fairly mediocre at doing what it is supposed to do. The compiler in the browser is going to run its own optimization anyway, preoptimizing the input isn't necessarily going to help.
- miloignis 6y agoHaving read the spec and proposals recently when looking at web assembly as a cross-platform bytecode, I have to disagree, it seems very well designed to me. They started with an MVP, and are continuously working on and adding proposals to extend it with more features, including some of the ones you want, I think. Why do you think it's a hack job? Additionally, I think optimized webassembly should normally be a big benefit, helping both startup time and optimizations the engine might miss (also helping the engine focus on other optimizations / making simpler engines performant). edit: Indeed, optimization before webassembly makes a big difference in the article's benchmarks, as you can see with how C++/Rust was faster than the hand-crafted AssemblyScript, theoretically because C++/Rust is going through LLVM optimizations.
- als0 6y agoCan someone explain to me why WebAssembly is restricted from accessing the DOM or the Web APIs? I haven't been able to find a reason.
- k__ 6y agoI'd guess, the main reason is that the standard for doing so is not fixed. The idea seems that WASM tries to be a general compilation target, so they don't wanna mess it up by integrating with the web platform too soon. Don't know when or if the interface types are released.
- brabel 6y agoBecause before it can access the DOM, it needs to support: * reference types * interface types * exception handling * typed function references * garbage collection I.e. most WASM proposals must be accepted before we can use the DOM from WASM... by the pace it's been moving forward, I guess this will take at least several years (3-4+). https://github.com/WebAssembly/proposals https://github.com/WebAssembly/proposals
- v8dev123 6y agoYou can access DOM and WebAPI using em_val. Emscripten provides the support. WASM doesn't however. It's complicated.
- mantap 6y agoYou can bridge through JavaScript. It's not a big deal in practice. WASM is still very immature. You do not want to build your whole app in WASM if you want to keep a full head of hair.
- TheCoelacanth 6y agoIt does limit a lot of use-cases from being viable in WASM. Anything that needs to do a lot of DOM access will probably see a big performance hit if you rewrite it in WASM because there will be too much overhead from crossing the JS-WASM border.
- danielheath 6y ago
- DonHopkins 6y ago"Dynamic Deoptimization" should have been called "Dynamic Pessimization". Debugging Optimized Code with Dynamic Deoptimization By Urs Hölzle (Stanford University), Craig Chambers (University of Washington) and David Ungar (Sun Microsystems Labs). https://bibliography.selflanguage.org/_static/dynamic-deoptimization.pdf https://bibliography.selflanguage.org/_static/dynamic-deopti... >Abstract: Self’s debugging system provides complete source-level debugging (expected behavior) with globally optimized code. It shields the debugger from optimizations performed by the compiler by dynamically deoptimizing code on demand. Deoptimization only affects the procedure activations that are actively being debugged; all other code runs at full speed. Deoptimization requires the compiler to supply debugging information at discrete interrupt points; the compiler can still perform extensive optimizations between interrupt points without affecting debuggability. At the same time, the inability to interrupt between interrupt points is invisible to the user. Our debugging system also handles programming changes during debugging. Again, the system provides expected behavior: it is possible to change a running program and immediately observe the effects of the change. Dynamic deoptimization transforms old compiled code (which may contain inlined copies of the old version of the changed procedure) into new versions reflecting the current source-level state. To the best of our knowledge, Self is the first practical system providing full expected behavior with globally optimized code. >Proceedings of the ACM SIGPLAN ‘92 Conference on Programming Language Design and Implementation, pp. 32-43, San Francisco, June, 1992.
- blippage 6y agoSeems to me that the flaw with WebAssembly is that it tries to fix the symptom, not the cause. As such, it's doomed to failure. Just stop festooning a site with pop-ups, trackers, geolocation, subscriptions and all the countless other crap that's increasingly being shoved into web pages. The problem will go away by itself.
- sesm 6y agoHere is a direct quote from the article: "WebAssembly, on the other hand, is strongly typed. It can be turned into machine code straight away." Decide for yourself, whether this article is worth your time.
- hutzlibu 6y agoI have not decided, whether reading your comment was worth its time, so maybe explain what you mean?
- code-is-code 6y agoHe is right. Implying that Webassembly is strongly typed is garbage and tells much about the rest of the content.
- hutzlibu 6y agoWhy is that garbage? Is this maybe something with academic definition of strongly typed? Because the way I understand Webassembly, it surely is strongly typed. edit: "Strongly typed is a concept used to refer to a programming language that enforces strict restrictions on intermixing of values with differing data types." https://www.techopedia.com/definition/24434/strongly-typed https://www.techopedia.com/definition/24434/strongly-typed Seems to back me up.
- rickbutton 6y agothis is nonsense. WebAssembly is strongly typed. either you don't understand type systems, or you don't understand WebAssembly. in either case, I can encourage reading the article, because it sheds some light on both topics!
- asimpletune 6y agoI think the author just meant their scripting language is strongly typed, but they says wasm because that’s the only target for that language. I wasn’t confused by that statement when reading the article. Obviously wasm isn’t strongly typed but obviously that’s not literally what the author meant. The article was interesting and they clearly spent a substantial amount of time creating it.
- unnouinceput 6y agoMayabe I'm a nitpicker by default, maybe it was so trivial that the article's author didn't thought of including it in methodology BUT before you test your speed of your port (regardless from what language to what other one) you test that end results are exactly the same. I see no mention of his port of blur functionality where he tested to see the results of original JavaScript blurring algorithm be the same of the porting one. And believe me, image manipulation can bite you in the proverbial rear at edge cases the best, I've been there. What I want is to see also testing included in the article, not just bench-marking his own solution. Try testing at least the classic 256 cases, that's RGB(x,x,x) (examples: RGB(0,0,0)-black...RGB(127, 127, 127)-gray...RGB(255, 255, 255)-white) then a few thousand random images. Only after that test you can safely move to benchmark for the speed.
- dassurma 6y agoI did test that and maybe should have mentioned it in the article :) The repo history actually still has an RGBA buffer dump I think.
- hutzlibu 6y agoThe headline is a bit missleading, as the main article is about AssemblyScript, a typescript subset compiling to WebAssembler. So it seems, quite some of the mentioned problems come from the immaturity (or design problems?) of AssemblyScript and not necessarily from wasm.
- dassurma 6y agoAuthor here. Using ASC was intentional, _because_ it is somewhat immature, and still manages to outperform JavaScript in the first two cases. In the third case, where I couldn’t get ASC to outperform JavaScript, I tried Rust and C++ as well.
- CyberDildonics 6y agoThat seems to mean every bit of your title is nonsense. You aren't benchmarking webasm at its best and 'magic pixie dust' is already nonsense on its own.
- 29athrowaway 6y agoJavaScript performance is completely vendor specific. There's no reference implementation for a JavaScript VM. So, it's more useful to talk about, let's say, v8 performance. Much of v8 performance is also version specific, and not all of it is documented. Code running on v8 can be blazing fast, or it can be slow. It depends on whether the code can be "optimized" (JIT compiled) and kept that way (because code can also be "deoptimized", meaning, the jitted version gets thrown away). With JavaScript, if you want to ensure your code always runs fast as it possibly can, you have to become acquainted with the rules behind optimization and deoptimization, and start tracing optimizations and deoptimizations to make sure that your code gets optimized, and stays optimized. This process can be time consuming and can make your JavaScript look non-idiomatic and less readable. In the other hand, WebAssembly performance is easier to reason about with respect to what's described above.
- f00zz 6y ago> Luckily, AssemblyScript provides a magic unchecked() annotation to indicate that we are taking responsibility for staying in-bounds. Isn't this a security risk?
- ludamad 6y agoNot if you control all the memory around it
- dj_mc_merlin 6y agoHow so? What are you going to hack by writing to out of bounds memory, your own browser?
- Ar-Curunir 6y agoEr, depending on how it’s implemented, you can use that to execute arbitrary code outside the browser sandbox
- RReverser 6y agoNo, that's never allowed - that's the strength of Wasm. Any unchecked helpers are for language-level semantic blocks within Wasm memory itself, not for leaving the sandbox. So worst case you might override and corrupt your own data.
- deleted 6y ago[deleted]
- TheCoelacanth 6y agoCould potentially be an XSS vulnerability. Imagine an HN-like page is written in this and uses unchecked in some code path for displaying user comments. I comment something that exploits that code. Then when you come along and view my comment. Now whatever my exploit does is running with your permissions instead of mine.
- vanderZwan 6y ago
- crazypython 6y agoDespite spending lots of time optimizing Rust and C++ versions, he didn't optimize the JS version.
- dassurma 6y agoThat’s the whole point. V8 is _really_ good at taking any form of JS code and making it fast, without me having to apply optimizations. The other languages only started being competitive once I hand-optimized them.
- crazypython 6y agoThanks.
- kohlerm 6y agoWASM is theoretically better for CPU intensive workload. As the article states even for CPU intensive workloads there are still quite a few limitations to take into account. What it is good for ATM is IMHO mostly just reusing existing C, rust, whatever (choose your WASM supported language here) code. Practically most web applications are not slow because of CPU bottlenecks but more because of too much communication, large code size etc. WASM at its current state does not seem to have an good answer yet for the code size issue.
- kodablah 6y ago> As described above, it is important to “warm-up” JavaScript when benchmarking, giving V8 a chance to optimize it. If you don’t do that, you may very well end up measuring a mixture of the performance characteristics of interpreted JS and optimized machine code. Since unwarmed first execution is a very common use case on the web, and a very intentional improvement for WASM, it seems foolish to discard that when comparing. I understand for benchmark determinism warming is important in long-running systems, but when parsing/warming is a common part of every run, it deserves to be factored in. I can make WASM look better by removing intentional benefits from JS before comparing too.
- tantalor 6y agoAs a programmer, there's a lot you can do to make your JS run faster under optimization (e.g. avoid deopt) but there's little you can do about the warm up (besides reducing binary size). So, when you're trying to progressively improve performance of specific code (e.g. boost FPS) the warm up time is better ignored; it's not under your control.
- TheCoelacanth 6y agoReducing size or switching to WASM are both things that you can do. You should measure the cases you actually care about. For a long running app, start-up time is probably not the most important thing, for other apps its very important.
- throwaway894345 6y agoI agree if the benchmark's use case were optimizing JS; however, the question we're trying to answer is roughly "how does JS compare to WASM?".
- dassurma 6y agoAuthor here! You even included in the quote: It’s important to warm-up the code is so you don’t measure a mixture of performance characteristics between interpreted JS and compiled jS. How long the warmup takes is _incredibly_ device dependent, so instead I measured Ignition and SparkPlug independently so you get a feel for the speedup. I did not discard that at all in the comparison.
- CuriouslyC 6y agoTry making realtime audio and video filters in JS vs WASM. There are some domains were there is a very real difference, and it is enough to put things in the realm of the viable.
- joppy 6y agoAs anecdata, I've also found that using typed arrays does not speed up (actually slows down, by 10% or so) code which uses integer arrays. Making sure that arrays stay in packed-small-integer format (which is not always obvious: for example one has to replace x => -x with x => 0-x to avoid the old IEEE -0 from kicking in) consistently outperforms typed arrays for me, by a large margin if allocating many small arrays, and by a small margin if allocating one large array. I found similarly "meh" performance improvements when trying to port my Javascript code to webassembly: either modern Javascript implementations are absolutely amazing, or webassembly runtimes still have a ways to go.
- vanderZwan 6y agoThis is most likely because allocating typed arrays is really, really slow in JavaScript. IIRC it has to do with the fact that there is a lot of flexibility regarding backing buffers or something; each typed array object has about 200 bytes of overhead compared to a dozen bytes for a plain array or object (roughly). Typed arrays are mainly faster in scenarios where you allocate one or a few large TypedArrays once and then re-use them a lot. That also explains your experience with many small arrays. That's basically the worst way to use TypedArrays.
- joppy 6y agoYes, I did think it wasn't a good way to used typed arrays, but I was still surprised that when allocating only a very small number of large arrays, just plain Javascript arrays outperformed typed arrays.
- yuri91 6y agoA good trick to convince JS engines that you are dealing with integers is to use the "`|0` operator": let a = 1; let b = 2; let c = a+b|0; // c is guaranteed to be a 32 bit signed integer This not only ensures correct 32 bit integer semantics (like wrapping around), but also helps the engines to use actual integer instructions in the generated machine code. For unsigned 32 bit integers, there is `>>>0`, and for multiplication, there is Math.imul().
- dahfizz 6y agoIs there a good comparison between different WASM languages / compilers? I imagine that, since we are in the early days, performance between compilers could vary significantly. Compare to V8, which has had thousands of man-hours from high level engineers.
- dboreham 6y agoAssuming that WebAssembly is for performance is an invalid assumption. The reason for WebAssembly is to provide a runtime environment for AOT compiled languages such as C++, Rust. The performance of programs written on those languages and compiled to the Webasm target may or may not exceed the performance of a program of the same functionality written in JS and executing in the same V8. There's no reason to expect performance to be radically different just because it's Wasm.
- dreamcompiler 6y agoI'm confused: The benchmarks seem to suggest you'll get best speed in many cases by just writing JS or TS. What's the advantage of AssemblyScript? If the issue is warmup time, do there not exist AOT compilers for JS (or TS) to WASM?
- admax88q 6y agoJavaScript is fast. The browser is fast. But communication between the browser and javascript is really really slow. They are written in languages with incompatible memory models, so lots of data must be copied when communication. They are running in different runtimes, so your javascript JIt can not inline function calls into the DOM. That's why to this day, if you want to render a bunch of html from javascript, it is faster to generate a giant strin g of markup and pass that to the browser in a single 'innerHTML = "foo"' and let the browser parse all that, than it is to call a bunch of "createElement(); setAttribute(); appendChild();" calls.
- zemnmez 6y agoI benchmarked this recently and I am pretty sure this is not true. Many of these 'single page site frameworks' work via this method.
- admax88q 6y agoYou are correct, I just did my own benchmark, and the DOM approach is no longer correct. It used to be the case a number of years ago when I last benchmarked.
- tiltrus 6y agoCan you share any benchmarks indicating this?
- admax88q 6y agoI whipped up one here with a random comment dump from HN. It appears I'm no longer correct. https://gist.github.com/adamvy/afcace8cbdbe56995626f59f6ea2b9f2 https://gist.github.com/adamvy/afcace8cbdbe56995626f59f6ea2b... Load this as a script tag in an html file to run. Last time I benchmarked this it was true, but that was a number of years ago.
- admax88q 6y agoActually, fun fact, if you remove the clearing of the body, the HTML approach is faster. At least in firefox here. Benchmarking is difficult.
- Ashanmaril 6y agoThat was a really informative read. I think myself and many others figured the biggest issue with WASM right now is purely the inconvenient development flow, and if you are willing to put up with it you'd just automatically get better performance. But there seems to be much more to it than that. I hope WASM can continue to grow in both of those areas, cause I still like the idea but it's clearly still an immature technology.
- bowd 6y agoTotally unrelated to the content (which was really great), I found it interesting that he shared his benchmarking setup as a _private_ gist (https://gist.github.com/surma/40e632f57a1aec4439be6fa7db95bc88 https://gist.github.com/surma/40e632f57a1aec4439be6fa7db95bc...) which is actually more like an opaque repository with multiple files. It has forks, revisions, probably some tooling built around (git -> gist) but it's not indexed and can only be found by finding the link somewhere (in most cases). Is this a more wide-spread recent pattern? Wondering what's the desired outcome in how it compares to just a public repo.
- throwaway189262 6y agoSome things. WASM binary size is highly dependent on optimization level. If your WASM is anywhere near the size of your JS, something is off with your compiler settings. Since Rust and C++ are statically typed, compilers can use LTO to remove almost every unreachable instruction. JS, even with tree shaking, gets nowhere near this. Default settings in Emscipten generate huge binaries. Rust without the "native" target or a bunch of configuration also does. WASM bytecode is also more compact than JS. There's simply no reason the binaries should be even close to the same size. The memory usage should also be different by and order of magnitude. WASM has basically no overhead above machine sizes for most types. Look at Benchmarks Game, memory use JS vs Rust. You should be seeing a difference close to that. I can't speak for speed. But I can say I did a head-to-head comparison between the fastest pure JS PNG encoder I could find vs a C encoder transpiled to WASM, and the transpiled encoder was >10X faster. It's hard to say if something is off in the benchmark or compilation but I find it hard to believe there's such a big difference between my tests and yours. Emcripten especially is not exactly easy to use and maybe a good place to look for size and speed optimization
- rkangel 6y ago> WASM bytecode is also more compact than JS. There's simply no reason the binaries should be even close to the same size. The author does explain this pretty well. For an exact 1:1 comparison, yes WASM beats JS for size. JS comes with built in functionality (e.g. a garbage collector) that doesn't cost any size, but in the WASM case needs to be brought along taking up space. Even if you don't want GC, you don't get any WASM 'standard library'.
- navaati 6y agoA bit off topic but what is the status of the hypothetical norm that would allow to do DOM/Web APIs call natively from WASM without JS wrappers ? Because afaik it is one of the biggest blocker regarding WASM application (not compute-heavy libs) performance.