-
Notifications
You must be signed in to change notification settings - Fork 843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixing wasm-bindgen benchmark #589
Conversation
Thanks. Results have been updated. |
I'm surprised this implementation is slightly slower than the VanillaJS. @Pauan do you have any insight into why that may be? It seems to me that theoretically this should be faster. Am I wrong? |
@deklanw No, it is expected that it should be slower. There is a lot of overhead when communicating between Wasm<->JS. Some of that overhead will be fixed in the near future, but some of it is unavoidable. As an example of overhead, wasm-bindgen creates a simple heap in JS. Whenever you send a JS object to Rust, it stores that JS object in the JS heap, and then sends the index to Rust. This is necessary because Wasm cannot access JS objects, it can only access integers. So we have to use a JS heap to "convert" a JS object into an integer index. Then whenever Rust needs to do something to that object (call a method, call a function, etc.) it has to send that index integer back to JS, then JS looks up the object in the heap, and then calls the method. And finally, when Rust is done using the JS object, it then calls a special JS function which removes the JS object from the heap, which then allows the JS engine to garbage collect the object. As you can imagine, this adds some extra cost every time you do anything involving JS objects (including the DOM). The cost is extremely small, but when you're dealing with thousands of objects it adds up. As a more serious example of overhead, in the case of strings it has to do a full Wasm is much faster than JS as long as you stay entirely within Wasm. But the more that you communicate between Wasm and JS, the slower it will be. So a web app where 99+% of the time is spent calling web APIs will of course be slower than pure JS. However, it is not hopeless, because I am working on a pull request which adds in string interning to wasm-bindgen. That means it can completely avoid the And soon browsers will have support for And within the next couple years we should get WebIDL bindings, which will allow Wasm to call web APIs (such as the DOM) directly, without needing to use JS at all. Because it is statically checked and doesn't go through JS, this should allow Wasm to call web APIs faster than JS. I'm actually quite impressed that wasm-bindgen manages to get almost the same performance as vanilla JS, even though it has a lot of Wasm<->JS overhead and string copying + encoding. |
@Pauan Ah, that explains it. Thanks. I wasn't even sure if this was calling the web APIs directly or not. That it isn't explains a lot. Once those direct bindings are available Rust can take potentially take over the frontend >:) Seriously though, how do you see Rust + WASM's current role on the frontend? Best used for intensive calculations? Worth using now for other stuff? Something else? |
Well, there's not much stopping it from taking over the frontend right now. Sure the performance isn't as good as JS when calling web APIs, but it's much better whenever you're not calling web APIs. Overall the performance is still very good (and will only get better over time). And you get to use an excellent language with static typing, nice features, good documentation, good tooling, etc. Overall using Rust is a lot nicer than JS. Plus, if your server is written in Rust (which it should be), then sharing Rust code between the client and server makes a lot of sense.
Of course Rust will be best at things which are self-contained, like encoders/decoders, CPU crunching algorithms, cryptographic algorithms, etc. But it still works quite well in areas where it wasn't intended. For example, I'm currently using Rust + Wasm to create Firefox / Chrome extensions (which are normally written in JS). I'm quite happy with the end result: it's far more maintainable than using JS, and the performance is generally very good: unlike For example, in one of my extensions it was using the standard JS I'm also using Rust + Wasm for a web game I'm working on. So it can be used for pretty much anything. I personally use Rust for all my personal projects, I see no reason to switch back to JS. |
Thanks for the involved responses!
For my new toy project I'm using Svelte on the frontend and actix-web on the backend. When the Rustaceans conquer I'll be ready :p I must ask, though, what code sharing do you find to be useful? I've heard this argument before for various stacks but when I think about it I can't think of much. Form validation rules, maybe? GraphQL et al cover typing APIs. I'm still not convinced about using a lot of Rust for web dev, front or backend. It seems like the mental and syntactical overhead of avoiding GC might not be worth it. It certainly seems to me that few JS developers will convert. Most frontend sites I can think of are usually not going to be CPU-bound. Are there any Rust frameworks in the works which give you some nice higher-level abstractions, terse code? I'm genuinely interested in trying some out.
To be fair, there are other languages that do this already with a similar or better type system (without needing to think about memory management). Elm, ReasonML, PureScript. Hell, even TypeScript is pretty good on strict mode. Elm/TypeScript have very good performance options, ReasonML you have React bindings with its performance, and PureScript is........ not concerned with performance.
What are the most common apps which would noticeably benefit from Rust on the frontend, but which aren't making heavy amounts of DOM API calls? |
What I use it for is sharing serialization. All you have to do is slap a And any methods defined on those types can often be shared between client and server as well. Also, libraries can be shared, tools can be shared, documentation can be shared, your mental model can be shared, and any helper utilities you create can be shared. I haven't done much server-wise, so that's all I can say about that.
It's not actually a big deal. You just create a top-level I agree that few JS developers will convert, but that's fine, they don't need to.
I had looked at essentially every compile-to-web language (all of those you listed and a lot more), and none of them were viable (for my desires), until I found Rust. I'm probably the only person in the world who desperately looked for a compile-to-web language before deciding that obviously the best option would be a systems programming language without a GC. Obviously. Even though I had never used a systems programming language before, and even though every language I had used before had a GC. As you can see, I'm very good at decision making. I even started learning Rust back when
Yeah, I use TypeScript at work. It's... better than JS, but not very good. Too many quirks, unsound type system, lack of useful features (typeclasses, nice ADTs, etc.), poor syntax (inherited from JS).
I used to use PureScript, then I switched to Rust because PureScript is indeed very slow (understatement), with no intention of improving.
Well, I'm not the person to ask that, since I would say "rewrite All The Things in Rust". But I think a better way of looking at it is this: you can seamlessly blend Rust and JS together in the same code base. So you can put things like business logic in Rust, and put the DOM code in JS (using whatever framework you want). Then the JS code can call Rust functions and vice versa. So you can surgically replace some hot JS functions with Rust code without rewriting everything in Rust. I think that's going to be a big selling point of Rust: the ability to replace bits and pieces of code piecemeal with Rust, while keeping the rest of the app the same. The reason why Rust specifically is so good at this is because other languages have a GC and runtime. Adding a whole GC and runtime just to improve the efficiency of a hot function isn't great. And you also have to deal with things like GC cycles between JS and the other language. Rust doesn't have any of those problems, since it doesn't have a GC or runtime, so it's very lightweight and has no GC issues when interacting with JS. This makes Rust the ideal language for embedding within an app.
I know of a few, but since I'm biased I'm going to shill my own framework dominator. It has a full featured TodoMVC example (or the much simpler counter example) and I'm using it for Real Things(tm). We should probably move this discussion over there, so we don't clutter up this PR. |
No description provided.