Supercharging React Apps with WASM
AI Generated Video Summary
1. Introduction to WebAssembly
Of course, like Nataniel said, it's my first time and of course my laptop has to die and I was supposed to show a few demos, but I'll improvise. Anyway, so today, thanks for making it and I'm going to be talking about supercharging React applications with WebAssembly.
Now, but first, let me introduce myself a bit. My name is Mukun, I'm from the south of India. I'm a software engineer based in the Netherlands in Oortek. Previously, I worked as a backend developer, mostly function as a scientific programmer, but slowly I started making my transition into the front-end world. Well, which was a quite an interesting experience. I have a unique perspective to see all these different technologies sharing the limelight, right? Along the way, I discovered Wasm or WebAssembly. I'm going to just call Wasm because it's much easier.
So why should you care about WASM or WebAssembly? You might think, oh, this is just another technology.
It's probably going to be a fad. I'm not going to invest my time in learning it. But I'm going to tell you that it's a bit more interesting, and I will tell you why. There are three reasons. First one, zoom! Well, yeah, it worked better in my head. But it's really fast. But then you also see a tiny asterisk in the bottom, terms and condition. When I say it's really fast, it's really fast in terms of execution speed, which means, since we're talking about source languages like C++, or Go, or Rust, we're talking about statically compiled languages, we're talking about compiling ahead of time, right? So execution-wise, it's set to run at near-native speeds.
The interpreter does a few interesting things. This is where the whole just-in-time compilation comes in. I apologize for oversimplifying this process, but to keep it brief, the interpreter throws out two different outputs. You have the non-optimized machine code and you have the optimized machine code. In order to get it running as soon as possible, the interpreter spits out this bytecode, which is, of course, from the name. You can imagine it's not optimized, so it's slower than the performance results that it could achieve. But then during runtime, it also sends out profiling data or heuristics to the compiler or to the profiler. It would send more information to the compiler to spit out optimized machine code. This runs orders of magnitude faster than the bytecode, for instance. But then here, if the heuristic or the assumption goes wrong somewhere, then there's this de-optimization process that takes place. And this is the main difference between this process and what WebAssembly does.
So keep this image in mind. How does this compare, or how does this contrast to WebAssembly? And then boom, you only have the equally crappy, but optimized wasm package that you initially compiled from a source language, and then you send it directly right over to the compiler. You see that all of the intermediate steps, all of the fluff, so to say, is not present, and then the compiler takes care of it, and spits out optimized machine code. And the keyword is optimized machine code, because we're talking about statically compiled languages. Here you don't see a process of optimization and de-optimization going on. And that is the primary difference between the two processes, in my opinion.
This is where I was supposed to show you a demo, but I'll just go through the basics of the demo and what it's supposed to represent. One of the demos that I created in my computer, which exists in my computer, it uses image processing techniques. Image processing, if you know, it involves a lot of computationally intensive process.
4. Image Processing and Machine Learning
To solve the problem of image processing, you can either use a client-server architecture with a REST API layer, which introduces latency, or you can use WebAssembly to embed the image processing code in the client. I used the Wasm library called Photon, written in Rust, to simplify the implementation. For the second demo, I used a machine learning technique called linear regression to predict stock prices. I used both an npm package and a custom Wasm package written in Rust for this application.
One way is immediately, we can think of client and server type of architecture, where you build different services, you have your front-end separately and then you have your back-end separately, and you can let them interact over a channel, for instance, HTTP, and then you can build a REST API layer on top of your back-end to communicate, to expose your back-end. This is completely fine. This is quite standardized and it's used in production in a lot of places, and then you also see these layers, but then in my opinion, with each layers, you sort of introduce latency and you sort of increase the response time. But I'm looking for rapid response. I'm looking for click of a button, I get my process image back. But that's just, well, you could try to achieve it but there is a sort of limitation posed by that communication channel and also the response time taken by the back-end.
The second thing that you could do or the second approach that you could take is use WebAssembly. Here I sort of take this back-end that you see, it could be written in any framework or any language. Typically, image processing is quite popular with C++, but in this demo that I made in my computer, which is in my computer, I made it using Rust. So you take that back-end and then you sort of quote unquote embed it in your client and then that way you sort of, well, you remove that particular arrow mark, which typically represents the HTTP layer of communication. You have it all in your browser, right? So, if I go back to the slide, now I'm going to be, well, obviously following the second approach, I will take the client-side approach and then I'll also take the out of the box, I already have the package, I don't have to worry about the implementation. Well, implementation approach. I used Wasm library called Photon, it is completely written in Rust, all credit goes to the author, Sylvia O'Dwyer, but then she also did the courtesy of creating a Wasm package out of it, so that all I need to do is just import the Wasm package and then use the functions for my image processing needs. So it's as simple as that. Here I was going to go through the demo, I was going to show you the different image processing, let's just imagine it in your head that it's happening and then maybe I can show you outside of the room. So the second way is of course the Wasm way. Here you see that it is as simple as importing the Wasm package and then for instance if you want to apply a Gaussian blur, which is something that you would do to process the image, you could just call the function and you could get the processed image as an output.
The second demo is, well the demo or the application that I made, is uses a machine learning technique and it's, well if you know about machine learning, it uses a lot of linear algebra, a lot of mathematical optimization. Again very computationally intensive process, right? So in this application I tried to predict the target using a target variable, using multiple features. I used a data set where there are different stocks, well I used the data set where there's a stock of the company over a span of a year and I predicted using different features which is like opening price, closing price, minimum price and maximum price. I do this via a linear regression, if there's any data scientists in this room please don't kill me because this is a terrible way to predict stocks. So, in this application I used two different framers of course. I used an npm install package, believe it or not it was quite difficult to find a suitable package that would give me, or that would allow me to carry out linear regression. And then I also use a wasn't package which I've written using Rust, but don't worry I also use the Data Science Package in Rust to do this.
5. Advantages of WebAssembly
If you have a lot of legacy code in your company or if you're trying to migrate to the web, WebAssembly is a great option. It's not difficult to pour over your code.
WebAssembly for UI Component Library
Examples of WASM in the wild
Web applications are utilizing WebAssembly (WASM) in various ways. Startups are incorporating Rust libraries, especially cryptographic ones, directly into their web applications. AutoCAD, previously limited to client-side use, is now accessible on the web. Another notable example is Figma. These advancements in WASM allow for more accessibility and usage of large-scale applications.
What are the examples of WASM in the wild? I know you talked about maybe Google Earth and a few others. Are there any other notable examples? There are a lot of startups that are using Rust libraries, especially cryptographic libraries, directly in their web applications. I think that is a very interesting field. And yeah, AutoCAD is an engineering application that was typically only client-side. And now, it's available for the web. I love it. I love seeing some of these really, really big things that were very heavy almost, being able to be more open for more people to use and access. Also, one more notable example is Figma, which also uses didn't know that. Today I learned. Today I learned.
Optimization and Performance in WebAssembly
When using WebAssembly, you don't have the optimization, deoptimization cycles. The performance is already quite fast, especially with languages like C++ or Rust that don't have a garbage collector.
OK, another question for anonymous. Since we're skipping the optimization step using WASM, we would lose runtime optimizations then? Or are we just skipping the initial optimization? I'm not sure which optimization that should that the quite if I remember correctly. On your side, you had the one with all of the different steps, and then the code was not optimized first. And then it was right, optimize and reoptimize. But now in the next one, when you showed are we skipping that optimization step? I'm trying to interpret the question. Sorry. Are we skipping that initial one or are we still doing runtime optimization? Well, like I mentioned, you don't really have the optimization, deoptimization cycles. But it also depends on the source language that you use. If you use, for instance, C++ or Rust, it is already quite fast and they don't feature sort of like a garbage collector. So the performance is quite fast to begin with. And that's that's the main reason you don't need deoptimization step.