Its common to only hear Wasm talked about in contexts that seem… advanced. How can mere mortals like us hope to build with it? Patrick Dubroy talks about flattening the learning curve and putting Wasm in context.
Its common to only hear Wasm talked about in contexts that seem… advanced. How can mere mortals like us hope to build with it? Patrick Dubroy talks about flattening the learning curve and putting Wasm in context.
Resources & Links
Read the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello and welcome to another episode of wait, what are we doing? We're doing the web dev podcast. Hello, welcome to another episode of the web dev podcast. Today on the show we are going to dig into one of those technologies you hear about all the time, but it's not often you actually see it in action, and I want to find out why that is, how we can take advantage of it. Today we're going to be talking about WebAssembly. So, WebAssembly, for those of you who are not familiar with it, is a way for people to, you know, build really, really advanced stuff that lives and runs completely in the browser. I only sort of understand what it talks about, so I brought along an expert to help us tease apart and show us how we can take advantage of it. So, I want everyone to please welcome to the stage Patrick Dubroy. How are you doing, Patrick?
PATRICK: I'm doing fine. Thanks. How are you?
JASON: I'm doing great. Thank you so much for being here today. I, you know, we've talked about WebAssembly on the show a couple times in the past, and historically we've been kind of like using a framework that will convert something to WebAssembly, or we've been kind of doing something WebAssembly adjacent, but we haven't dug into really the nuts and bolts of WebAssembly itself. And, so, I'm really excited to have you on to talk about that, because you quite literally wrote the book on this, am I correct?
PATRICK: I wrote a book on it, yes.
JASON: Yeah, so, maybe just start there. Give us a little bit of a background on who you are, what you do.
PATRICK: Sure. Yeah, so, I'm Patrick. I'm an independent programmer, researcher. I'm the maintainer of an open source library called OMJS, which is a parsing tool kit for JavaScript and TypeScript. And I started experimenting with WebAssembly actually in that context, and then decided to write a book about it with my friend Mariano, so we have a book called "WebAssembly From the Ground Up," which, yeah, the idea is to take you through really take you through to the details of WebAssembly by helping you to build a very, very simple compiler in JavaScript. Yeah, and before all that, I spent a few years at Google on the Chrome team, and also on the Android team. Was a lot of fun, so, yeah.
JASON: So, your interior's pretty deep, and it seems like that actually tracks with my general experience of WebAssembly, is that as far as I can tell, the people who really seem to leverage it are people who are pretty deep in the stack. Do you think that is actually, before I dig into the why, let's talk about what. So, at a very high level, can you give us the elevator pitch on what is WebAssembly?
PATRICK: Yeah, sure. I think I'll bring in some of the history, I guess, is also helpful to help explain it. So, yeah, at a high level, WebAssembly is a way to take native code, typically, that was maybe written in C++ or Rust or something like that, and run it efficiently and safely in the browser. And historically, the first people who were trying to do stuff like this, you know, were working with games. One of the big use cases was to take games that had been written in C++ and get them working in the browser, and the way that this I mean the first kind of viable way of doing this was something called AsmJS, and this was basically a restricted form of JavaScript that the browser began in Firefox, but later other browsers added support for this. They would sort of if you wrote your JavaScript in a certain way, and you used use ASM string tag at the top kind of familiar, because this sort of thing is coming back now, putting strings at the top of your JavaScript to give it special meaning, but the JIT would recognize that this was a restricted form of JavaScript and could do a bunch of optimizations that it couldn't otherwise do in JavaScript. And this worked pretty well and kind of proved that the kinds of things that you would use C++ for, you could get a JavaScript JIT to, you know, give you nearly the same performance that you would get running that code natively. The big problem with ASM JS is it was quite large. So, if you took a game and compiled it down to this format, you would have huge bundles. And, so, WebAssembly kind of then was an attempt to say, hey, can we take this same idea of being able to ship code, native code to the browser and have it execute it safely. But do it in a much more efficient way, so it's a basically, an efficient binary format for shipping instructions to the browser and the JIT can then turn those instructions into native code for your CPU. So, it's a platform independent representation that gets shipped down to your browser, similar to conceptually similar to Java by code or something like that. Yeah, your JIT will compile that down to either X86 or ARM machine code.
JASON: Got it, got it. Okay, so, to hear you describe that, it sort of brings me back to what we were saying before we did the history. It feels to me like most of the people I see really leveraging are pretty deep in stack, are people, you know, would kind of get the, oh, you're pretty hard core when you talk about what you do for work. Hearing that you've worked on the Chrome team, you know, you're sort of in the browser world and pretty deep in it, is that, do you think, an artifact of like WASM being WASM being hard, or if you're in that world, deep in the browser, you get exposure to be more willing to try it?
PATRICK: I don't think it's so hard core and difficult to understand, because otherwise I wouldn't have written a book about it. I mean, part of our goal with the book was to try to open that world up to people, and one of the choices early on we made with the book was put all the code in JavaScript. We had thought about whether we should do it in Rust instead, a lot of people working with WebAssembly are working in Rust, and we chose JavaScript because we wanted it to be as accessible as possible. I think you're right that either people are working with Wasm by writing their code in a language that simply compiles to Wasm, and you're not really working directly with it in the same way you're not working with ARM because you have a MacBook. It's executing, but you're writing your app code in some other language, so a lot of people work with Wasm in that way. They have a compiler that produces Wasm in the end, but they are not sort of interacting with it at a very low level. But, yeah, I happen to think that Wasm is kind of special, because it's a low level language. It's really nearly as low level as ARM or X86 assembly. Slightly higher level. But working with it is much, much nicer than working with any kind of assembly language. So, the tooling that you have is much nicer, and just the whole environment is you know, things are easier to debug, you have a validation pass, which if you screw up in your instructions, will tell you that you messed up, rather than just saying segmentation fault or something like that.
JASON: Yeah. Okay, let's talk a bit about practical application a bit. Maybe the other gap that I felt in my own like world of encountering problems I would solve with Wasm, a lot of times what I'm seeing about how to solve a problem, WebAssembly doesn't ping as a valid solution. I think that's due to my own limited understanding of like where its soft spot is. Because I might not even write about this. The only major implementation of WebAssembly that I'm aware of, I believe, is Figma. Is that correct? Is Figma WebAssembly?
PATRICK: I think large parts of it are in WebAssembly, yes. I think Adobe Photoshop, the web version of that also is.
JASON: Oh, right, yeah.
PATRICK: But I mean I think one of the things about WebAssembly is that people just don't tend to talk about it when they are using it. It's not really a user feature, right. You often hear, yeah, we made our site, we made our compiler, we made this or that 10x faster or whatever the case may be, and they don't necessarily tell you it's because of WebAssembly, but, you know, under the covers there are, you know, many libraries for, say, image processing. I mean, it needs to be a certain type of code that will benefit, because JavaScript
JASON: Yeah, and maybe we should run through that. Like what are like the core use cases, where it makes sense to reach for WebAssembly, because you couldn't really do it in JavaScript and they don't necessarily want to have to fire it off to a backend server?
PATRICK: Yeah. I think there's a few major use cases. So, one of them is you have some existing app, right, that was not written for the web, and the app or a library that was not written, you know, in JavaScript or for the browser, and you simply just want to use it. So, a lot of people have that kind of use case. So, you have, say, physics libraries that were written in C++ for games, right, and someone wants to use them in their web based game. Or I've even seen sort of layout libraries, UI libraries. So, there's popular UI library called Dear M GUI, which is used in games. Does this sort of immediate mode GUI style, which a lot of people like, and you can use that on the web, just kind of for free because of Wasm. So, you know, that is one big use case. Another big use case these days is actually cloud computing. So, for serverless environments, you know, WebAssembly, like a lot of the providers already had JavaScript run times, like V8 for writing serverless functions, first version of AWS lambda, if I remember correctly, only supported JavaScript. And because of V8 as a runtime also supports WebAssembly now, that now means that kind of for free companies like Amazon, who are already letting you write lambda functions in JavaScript, can now say, oh, you know what, any language that targets WebAssembly you can write your lambda function in.
JASON: Uh huh.
PATRICK: So and there's some benefits for the cloud computing, for the hosts, there are some concrete benefits to WebAssembly, basically.
JASON: Well, so if you take your serverless functions and compile them into a WebAssembly format, you're getting a more efficient final bundle, right, because you've sort of taken it down to this more low level, there's less work to be done by the server during the serverless call. Is that a correct assumption?
PATRICK: It's I mean, it depends, I guess. It's not always less work. Often it can mean faster start up time. So, if you look at the pure top end speed of code, you know, the highest optimizing tier of the JavaScript engine can do is extremely fast and is unlikely to be faster than WebAssembly. So, if your JS code has the right shape, you know, Turbo Fan, which is the, you know, the optimizing compiler in V8, can make it crazy fast and your WebAssembly is not going to be faster. But the WebAssembly getting to that top level of performance in WebAssembly is kind of simpler for the runtime. It's also often usually preoptimized code. So, if you have code that was produced by a C++ compiler, the Rust compiler, that final code goes through a relatively long optimization pass to produce the final binary that you upload. Many of the same optimizations, V8 would have to do on your JavaScript code anyways, and they would be expensive.
JASON: And right, if you're doing that on something that's like in a loop, it's worth it, because in JavaScript it's like a little less work, it does the one optimization path and then it runs it a thousand times and great. But like a lot of times we're doing one image to be light transcoded or sending one, you know, one thing that needs to be posted to a different places. So, if we have that long optimization pass and we only do one operation, you know, we're kind of wasting time. And you're wasting compute if it has to fire up every time. Whereas if you do if you have it kind of pre optimized and set up as binary, then if a thousand people do one path, you don't have to run that optimization for every call. Is that am I kind of understanding what we're getting at here?
PATRICK: Yeah, yeah, absolutely.
JASON: So, it starts to really show it starts to show its strength when you think about like distributing these systems. When you take something online and you've got a lot of people doing something, and I think this is why you see like Figma spend so much effort on getting the Wasm stuff going. Trying to run all the different things you can do on Figma in JavaScript, that would be a nightmare. I don't think that app would run at all if you were trying to run that all in client side JavaScript. So, I can see and that again kind of points to the sort of heavy duty use cases, but also your co author Mariano was in chat, he was talking about we can use it for image and audio and video, transformations like format quality, listed off Shopify and a flight simulator, which is kind of fun, and rules and filters for Nginx, CloudFlare, and Fastly. So, all of that kind of points to it's really good at what I would consider to be utilities. Is that maybe a safe bucket to put this in, like if you're writing a lot of code that's like we have a service, the service requires us to take input from one place, transform it in some way, and put it in another place, and that happens lots and lots of times by lots and lots of people, then that transformer layer is probably a good thing, considering could we make like less work for the computer and faster to execute if this were to be converted into Wasm, could we maybe move this off a server and into the browser for something like image transcoding. There's some interesting considerations there in terms of, you know, like what work are we doing and I know, for example, I work in media, and a lot of times I feel like I am uploading something to a server, where I then have to wait that server to get through optimizing my media or doing whatever it is that it does, and then that has to get sent back to me to then be available to my frontend. And if that were to happen on my browser, I do it often enough that would actually be a huge cumulative time savings over the course of a year to not have to upload a 1.5 gigabyte file every time I need to make a change to it.
PATRICK: Yeah.
JASON: So, that's me sort of applying my own problem case to where this feels really interesting. Have you seen do you have any like favorite apps that you've seen or favorite case studies of where this really made a big difference?
PATRICK: Well, my favorite one right now has to be probably the parsing library that I work on, so, which I mentioned earlier, called OMJS, and the basic idea is there's all kinds of reasons why people, you know, might want to either quickly parse some existing language or in many cases people design their own language. So, that was the original reason we created Ohm, we wanted to be able to try out new syntaxes and quickly build an interpreter compiler for it. Shopify is also using this library in their product, so they have a template language called Liquid, and when you design you can edit your themes for your store by editing this template language. And all their developer tooling, VS Code plugins, things like this, use this library Ohm that I'm maintainer of. And when we originally created Ohm, the original implementation was all in JavaScript, and it wasn't done in a particularly efficient way. And for the past year or so I've been working on a new version, which takes so, users write a description of their language, a grammar which describes what are the valid syntactical forms in the language. And it used to be we would use JavaScript to interpret that grammar, which would then let us parse some input. And we switched to compiling those grammars to WebAssembly, so we get the same benefit that you were talking about, we can do a bunch of work up front and produce an optimized thing, and then the JS engine at runtime can do a lot less work sort of making it fast. But we've seen I mean we've seen huge speed ups in the parse times now for this. So, the new version is based on WebAssembly, is sort of 40% to 50% faster, and uses about 20% of the memory that we did before.
JASON: Yeah.
PATRICK: So, that has been that right now is, I think, my favorite, you know, my favorite example. I think a lot of there are probably a lot of JavaScript libraries out there that could selectively look at parts of the library that are very compute intensive and could get benefits from switching those things to WebAssembly.
JASON: And so one practical question about this. Like let's say I am the maintainer of an open source package. I realize something I'm doing is a great target to be moved over into WebAssembly, because I can see huge savings. Once I've made that change, what does that mean for downstream users? If I, for example, have pushed this on NPM, does anything does the person downing that package, do they have to do anything differently, or is this a completely behind the scenes, no notice, accept that everything performs better?
PATRICK: Yeah, good question. It depends. I think you can certainly make it, you can do it depending on the scenario, it can be done in a way that sort of nobody notices. And is often done that way. There are a few gotchas around sort of working with bundlers, where if you're a library author and you start using WebAssembly, the people who are using your library may need to modify how they do the startup, like how they instantiate the library, and this just has to do with some of the complexity in how bundlers deal with shipping binary data.
JASON: Okay.
PATRICK: So, to be honest, there's no real good reason why it's like that, but the fact is that today, yeah, it could be that you have to tell the users of your library I mean, the change could be as simple as there's an asynchronous init that has to happen before you use the library. Before you did import lib and called lib.do something and maybe now you need to say import lib, lib.init, do something.
JASON: I got it, okay.
PATRICK: Or
JASON: Yeah. So, it can cause a little bit of a shift. It would probably be obviously, main version breaking change if you make that switch over, which seems reasonable. And there might be a little bit of a migration guide to getting from one place to the other, but it's not going to be like, hey, surprise, you're no longer using JavaScript, you're now using this other thing that you have to, you know, make sure you have Python installed, or make sure you've updated your Xcode or whatever it is. You still continue to operate within your normal runtime, not have to modify your dev tools stack or start thinking about it as being a different sort of thing. It's still, as far as you're concerned, it's a node library or node package and you can continue to use it, but little more setup to get it running.
PATRICK: Yeah, exactly.
JASON: Okay. No, that's great. So, any other question I have, I feel like is going to be a little easier to talk through hands on. So, I feel like I want to get to the episode where we're going to do, where we're going to get into some paired programming on Learn With Jason here, but before we do that, is there anywhere that you want to send people who want to learn more about WebAssembly and how this works? I believe there's a website for the book, right?
PATRICK: Yeah, that's right. The website is Wasmgroundup.com.
JASON: Let me get that in the chat.
PATRICK: Yeah, and I have a people could use the code "Jason" if they want, yeah, for the book.
JASON: Is it like a discount code?
PATRICK: Yeah, sorry. There's we have some free chapters on there, there are a couple of interesting blog posts, as well, that, yeah, sort of follow the same theme of the book of trying to get you familiar with WebAssembly by really getting your hands dirty.
JASON: Nice, nice, nice. Well, cool. With that, I think I'm going to take us out and just thank you so much for spending some time with us today. I really appreciate. Remember, everyone, there is a companion episode of Learn With Jason, where Patrick and I are going to get hands on building something with WebAssembly. So, if you want to know how it works, head over to CodeTV website or YouTube and look up Learn With Jason. This has been the Web Dev Podcast, make sure you like, subscribe, you can get it in video or audio format. We are everywhere that you would probably listen to a podcast. Patrick, thank you again for spending some time with us today.
PATRICK: My pleasure. Thanks for having me.