Rust in the Browser for JavaScripters: New Frontiers, New Possibilities

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] well thank you very much for that warm introduction I'm going to be talking about roasts for JavaScript errs show of hands who has heard of roasts before all right cool looks like no one raised their hands as far as I could tell all right but first a quick bit about me I'm Shawn growth coming out of San Francisco I work at a company called one graph but I don't really talk about that today I'll give a little bit of context about my experience with rust the main project I shipped in rust was a cross-compiled arm embedded system and in kind of an IOT device and so you can imagine that we have these bits of hardware that we're shipping out to the edge and we need to be able to push updates to them very very reliably and so we had a lot of performance and a lot of security and a lot of correctness concerns with this project other than that though I used to work a lot enclosure and clojurescript these days I mostly spend my time in reason and rust but I am here today to sell you on rust and this is serious business that's actually why I am dressed so nicely so that you know that this is serious business but I do have my button undone at the top so you know I'm trustworthy I'm kind of a chill business guy so with that said I've been practicing my pitch working with rust in the beginning is like banging your head against the wall I know we're all excited about that but I want to set expectations at the beginning of this talk it's good to think about rust from the negatives initially so you're at least setting expectations basically anytime you have a bit of JavaScript code if you write the equivalent in rust it will be longer it will be more intricate and we'll have a lot more symbols it's not always true but it's just a good attitude to have because it's true enough of the time now rust itself is described as a systems level programming language that cares about performance security and correctness I don't know if systems-level programming is such a good description for it because it goes in a lot of interesting destinations well that's how they describe themselves so we'll run with it but from a JavaScript is point of view Russ is interesting because it's low level very very very low level but it has a lot of abstractions and they focus a lot on zero cost abstractions in particular it also has guaranteed memory safety which is a big issue whenever you are working a lower-level language it also carries a lot about concurrency so has threads without data races and it has some nice things that kind of inherits some of the like reason type of features like type inference and pattern matching and has a very minimal runtime but why would you care why do you want to have low level but with abstractions rust is very focused on very predictable performance at any given time it's going to give you as much control as you need to eke out every bit of performance from your hardware this includes things like memory allocation layout garbage collection all that sort of thing but once you get access to all of that power basically you have this amazing gun that you will immediately point at your foot and pull the trigger it's very very difficult to ensure data integrity whenever you have this level of control in particular trying to maintain any sort of data integrity with that level of control with concurrency is next to impossible so many of the bugs that we face in our day to day usage of servers is because of threads with data races and type inference type inference is a topic that's near and dear to my heart but I would say before we explain what type inference is for like why not step back and actually ask what the hell are types for and if you ask C C says types are for performance types tell the compiler for all of your data how should I be represented at runtime both in memory and on the CPU and typescript and flow they don't care about the delay out of the data what they care about is correctness all right if you think about C it can't prevent many of the mistakes that you might have or where you pass one string when you should have passed an array I mean as long as they look like bytes it's fine and typescript you can add as many types as you want but it will never be used by v8 whenever you're actually running your code so you kind of have these two different values that Tice might offer and different languages will choose different pieces of it and Russ says that well types are for correctness and for performance why not do both and there is another language that has said this before Java I know Java is not very popular and if you look at Java right here so this is an example of declaring some variables in Java and you say hey I have an integer called number and it's 29 and I feel like this is like working with a compiler that's very hard of hearing right because I say hey my flag is false and you should know that it's a boolean right what else could it be I told you it's false but the compiler is like I'm sorry didn't hear you and so you have to kind of shout that's hey this is a boolean and you have to repeat yourself a lot so the idea is type inference actually says what if the compiler were to look through your code and say can I figure out the types for you so in this case I'm declaring a variable called elam and it's gonna be an element inside of my array and it's just five the u8 is a literal for an unsigned 8-bit integer you don't have to have it but it's nice if you want to have it and you see that I'm going to create a vector which is basically an array but I don't say what the vector is off I just say hey it's a vector and now whenever I push the element in to the vector Russ knows this must be a vector of unsigned 8-bit integers and the cool thing is that we have very very minimal type annotations that a programmer has to do but the compiler is still happy right the compiler can check for all sorts of bugs and it can optimize the exact memory layout of your code as much as you need and so the compiler is happy and the programmer is happy and it's kind of this principle in Ross where wherever possible the computer should be doing work for us rather than us doing work for the computer now why is a minimal runtime so important right so traditionally with things like C or C++ you're kind of targeting beefy machines right you're pushing to Linux somewhere and it has gigabytes of hard drive and gigabytes of RAM and it doesn't matter how big it is right because you'll download it once and it's fine but as we start to push to smaller devices or to the web in particular that puts a lot of pressure on how much data you can actually ship to your clients so go is another language that has been working really hard at having really great web assembly support the challenge is go was originally designed to run on servers where space and size are not a concern we care much more about performance than we do about size and so what that meant is that go has kind of built this culture where by default a hello world go application compiled to web assembly we'll start at two megabytes and if you pull in any library it's going to balloon to about 10 megabytes very very quickly and I'll give the credit there's work on a thing called tiny go which is a subset of go that starts at 10 kilobytes which is amazing but the challenge here is libraries actually have to add support for tiny go because the ecosystem has built up with this expectation that well having a big runtime is not a problem but rust was originally designed to go everywhere including embedded devices that are so small they can't actually fit Lib C so you can write a rust program that will compile with no standard library do you have to bring your own but that gives you the ability to define exactly the size and performance characteristics of your application and like I said it rust inherits a lot from the ML language of family so like Haskell or Oh camel or a reason in particular pattern matching so pattern matching is near and dear to my heart so you can see here that I have a list of greetings so there were three of them and what I'm gonna do is iterate over them and I'm going to get the index and the item and now I'm just gonna have a switch here basically match I'm going to say based off of this index I want to print out a different greeting so if it's zero uh printed English outs Korean or Swedish and this right here is not too bad right we can look at like the list of 1 through zero through one two and we can see that yes there are three greetings there but what happens when there is a third one right now we can verify it but what if these two bits of data were actually a part in the code base then what will happen is this will crash so what happens is russ has exhaustive pattern matching where it says I have detected a case that you have not handled and in fact I will not compile this because it is guaranteed to crash if this case happens and you can see here that it's giving me this nice error message the error messages in Russ are heavily inspired by those in elm so it's a systems level programming language that really cares about developer experience you can see that hey you didn't cover this underscore case which is kind of a weird thing to say what it's saying is I looked at what you're mapping over you're mapping over numbers it's really hard for you in one source code file to list every single number possible so you need to have a default case which is this underscore so it's literally telling you hey you need to add support for this default case if it was something else like say an enum that had maybe open or closed or some finite number of states it would have said hey you have open but not closed you should handle that case and the cool thing is they canonicalize all of their errors so you can see here if you want to know more information about that you can just say hey rust explain to me why why is it so important why are you bothering me about this and we'll actually print out documentation in your terminal or your editor saying hey here's a list of all the things that could go wrong that I'm watching out for you right now with this error so we add a default case and Russ is happy and we're happy because we know that this is never ever going to crash so from the correctness point of view I would say debugging sucks there is never a time that I'm excited about debugging unless it is so bad that I'm like oh man when I go to the pub tonight and I tell people about this oh it's gonna make for a great story but most of the time I don't want to be debugging so I say there are three questions from order of easiest to hardest about debugging the easiest is who should be doing the debugging second is when enter is where so who should do it well this is easy the language by virtue of construction the language should make it so that it is impossible for me to add bugs into my program wherever that's not possible because the language needs to give me more power that might introduce bugs the compiler should start checking my code right the compiler has access to all of my code it has access to all of my dependencies it should be checking through everything that the language couldn't to make sure that I didn't add any bugs and then maybe some automated tooling around like linters maybe this is something that my company has about some rules about how I should be coding finally there are tests if all of that fails and I'm I have to still debug then I guess it's me but if a developer doesn't do it then the user does it and that's the worst scenario right how many times have we been on a plane or train booking web site and you go to submit the form and it doesn't work and so you open up the console you get the HTML element and you manually submit it in the console and it works right so that it's possible for the user to debug and maybe that's a good thing but it's certainly not a great experience and so the question next question is then when should debugging happen and like Elm Russ says it should happen upfront you should push all of that up front because the moment that you introduce that bug is the moment when you had the most context to fix it so it's going to list out all of the bugs that you have it in a given time and say fix these before I compile and that means that by the time you actually get it to compile it just works most of the time it's actually a very jarring experience especially coming from something like JavaScript which is amazingly flexible and a lot of fun to program in but it will allow you to make mistakes that will take you a long time to track down and I want to give one last shout out to the Russ community here because they have built a crazy empathetic and welcoming community most systems programming languages the community is not known for being very welcoming but this community cares hugely about the experience of new developers and experienced developers so much so that they regularly have surveys about the experience of different parts of rust and then they will actually take the top pains and form a working group so they knew that web assembly was going to be a really important task for them so they actually formed a working group to say your job is to make it so that someone who doesn't know rust can come to this website read through the docs and have a fully working Game of Life in 30 minutes which is an insane task but it is they've done it so now why would you care as a JavaScript er and it's because russ now actually compiles down to web assembly and web assembly is pretty crazy powerful it is I think unprecedented and how well designed it is and how adopted it is usually a lot of great technology kind of never gets adopted I want to give another caveat here though using webassembly from javascript is currently a little bit on the idiomatic it feels a little bit weird but it's not too bad but that also means that because rust is compiling to web assembly that also be a little bit thankful but in particular rust is compiling down to JavaScript or sorry into web assembly and webassembly literally is just a big array of bytes ones and zeros there are no strings there are no floats there are just ones and zeros and all the things that we take for granted in JavaScript don't really exist there and yet we want javascript to be able to call functions and pass in data and retrieve data more than just maybe ones and zeroes so what we need to do is figure out how to interrupt between these two systems by default your JavaScript will load up it will reach out and download a big blob of wasum data it will instantiate it and pass in all of the functions from the outside world that the web assembly bundle is allowed to know about and then having instantiated it it can now call into functions that exist on the web assembly side so you can imagine here that I have my wasm and I call greet and I pass in hi that's going to go over to the web assembly side I've implemented a greet function there and I'm going to return a string back but this bridge right here going back and forth has to be implemented by me and when I'm implementing it I have a couple of different goals one is I want to minimize the copying because these are two separate worlds they both have their own view of memory there a memory does not touch one another and so that means if I were in JavaScript and I just copied a bunch of memory and sent it over to the other side that would actually be really slow it would put a lot of pressure on the garbage collection and it would kind of in many ways like defeat the points of using rust which is I want to have fine-grained control over memory allocation and performance so what we're gonna do instead is on the web assembly side and rust where going to create a huge array of memory and now on JavaScript we're going to actually just call a function like hey rust can you create the game world for me and this will initiate all of the or initialize all of the data structures the world the players etc and then it will just pass back pointers to JavaScript side and these are very very small and now javascript is going to just call functions using these pointers and rust will update everything and then javascript will be able to just reach into the memory and see the result and this is nice because javascript has so many things that we take for granted right access to dom garbage collection like you have objects objects are cool you have arrays and strings like things that you don't feel are very special but whenever you don't have them you you really miss them whereas on rust you have all this nice performance and memory management but you don't really have objects you have like structs and you have arrays and vectors and you have two kinds of strings for whatever reason rust people say they don't I always say they do so what we're gonna do is have this shared memory between them javascript will call into rust rust will update the memory and then javascript can read the memory so we have this nice cycle flowing a bit like react maybe and that means that we can make sure that we only pass small bits of data between the JavaScript and rough slide and everything is able to actually kind of exist inside of the un8 arrays but that we still have to on the JavaScript side even though we can read all those bytes it's still unpleasant we have to figure out how to construct strings and boolean's and whatnot from them but the rust people are aware of this and they have built phenomenal developer experience so what I've done here this is the game of life written in rust I have a cell which is an enum a cell in the game of life can either be dead or it can be alive and I'm saying hey rust I want you to represent this as a zero and I want you to this is a one the rest of the world should know but I care about how that's actually implemented in memory because I need that for performance or whatever now every tick that gets called from JavaScript I'm going to iterate through the entire board and I'm going to get a list of all the neighbors around the cell and now I'm gonna match and you can see this pattern matching again where I'm matching off of two items which is really cool and I can say hey if this cell is alive and the number of neighbors is less than two then the cell should be dead and so on and so forth so in this one line right here or this one chunk I can concisely encode all of the rules of the game of life it'll be type checked and will be immaculately out in memory now what Russ is going to do as part of this as an automatic part whenever they generates the webassembly code it will also generate an NPM package so that you on the JavaScript side will be able to pull in all of those functions and call them but not only that remember that rust is statically typed it has intimate knowledge of all of the types in your application so it will also generate typescript bindings but not type script bindings like I would writes where it's like oh it's any I'll come back and fix this later it writes them as though I were a really good programmer so now we can come in here and let's take a look at what this actually looks like with a real application so this is there's a component library or there's a library called you and you as inspired by Elm except that what it's going to do is you will have a JSX like syntax you'll have service workers that will get spun up in the background automatically to handle concurrency and Russ is going to guarantee that you have data integrity no race conditions all throughout the entire experience so you just write a normal rust application you compile it out and you can get all of these benefits so this is what it looks like to write a component using you so you can see I have this HTML with a bang this bang is really cool bang means this is a macro it's like a babble transform but it's built into the language so any library author can ship a JSX type of thing as part of their library they can bring the language into their domain and make it much more accessible and so this library has actually implemented their own HTML macro and all of these props here are actually tight so if you pass in the wrong type or you have the wrong children it won't compile so this is like an amazing experience to actually write HTML inside of this low-level language and have everything typed and compiled out nicely but then we have maybe events so imagine I have my in my core loop of my application I have a request so I'm gonna send this off to the service workers or they can send it to me and the response to it should come back as a answer what I'm gonna do is whenever I receive a signal I'm gonna match over that and say hey if the signal was a question then pull out the body and then send an answer to this saying hey that's cool and what this is going to do is this won't compile because the message might also be a response and also if I add for example maybe I have a question right now but maybe I want to add a demand later then if I add that in everywhere that reference is that will break and I will be able to go through and fix everything once compile it out and it will just work now this is what it looks like if you're actually consuming the generated rust from JavaScript so right here this import memory this is the big bit of memory that we talked about that the rusts compiler generated for us so we're gonna pull that in and then we're going to initialize it it's just a big array of bytes we don't really care but from then on we're gonna say hey get the sell at this index and if that cell is dead then I want you to draw a dead color or else use the alive color and the thing I love here is this is actually the enum that we defined in rust so we don't care if it was 0 or 1 or true or false or a or B doesn't matter we get to code as though someone were a really good programmer on the other side and they gave us this really good API and that's all generated based off of the deep knowledge that rust has about your program I'll give a quick aside about the syntax I mentioned before that you know rust is a bit more verbose but it is also very heavy with symbols so just be prepared but the nice thing is they care so much about developer experience and onboarding that the error messages will oftentimes navigate you out so for example here I have foo it takes a B which I said is immutable unsigned 64-bit value and being very specific about what I want here and it's like hey you are trying to borrow a mutable value you can't do that maybe you should try just removing the an mutable and what happens is it guides you out of this problem enough times that you start to develop kind of a muscle memory about what is this symbol actually doing so I want to give one demo of what this actually looks like so this is an NES emulator written in rust and it is super fast super cool if we open up the developer tools and we take a profile you can see that the animation or sorry each of these frames is tiny it's incredibly performance it's very good on my battery it's in fact been running in the background for quite a while and my battery is still doing fine but the cool thing is with Russ you can also compile out that same application to a native application so this is it running using SDL instead of web geo and this is super mario brothers using the same code that's type checked and you can run this on a desktop or a mobile or you can compile to the web as we saw with the other example and then there are some pretty other crazy things that are happening so in particular this idea of webassembly like I said is crazy well-designed and someone has actually implemented a web assembly to rust compiler so kind of like a D compiler and someone actually there's a subset of typescript called assembly script which is how a type scrip people go to web assembly it's kind of the non allocating subset of typescript and someone wrote a really cool Gameboy emulator in that and they compile it out to webassembly fast and cool but then someone took the web assembly to Rusty compiler turn that into rust and then they took the Russ code and compile it out to a native application so it's kind of a crazy pipeline but like the future seems very exciting I'm going to end on this note that I think that we are actually rust and webassembly represent a unprecedented opportunity in our industry because our industry only moves forward via secretion if there is any abstraction or any implementation that is even a little bit successful it never dies to that point I have a terminal in my computer a terminal is a end point like a keyboard that talks to a mainframe right and my terminal understands crazy old Escape codes but that can never go away we are stuck with it forever and we're also stuck with like Lib C and Lipsy has caused unprecedented amount of good but also tons of security issues it has been very difficult to actually ship anything reliably with it and webassembly and rusts mean that we actually have a platform that it's not it's not in our best interest to ship all of Linux all of Lib C to the browser we need to have a new smaller implementation of these things and maybe we can do it in a safe language that's also fast and also correct and that could be rust and I actually think that in the next five to ten years most of the JavaScript that we run will be written in rust I don't think most people will write rust but I think that most of the code we run will be like who will actually write it it's the people who really want fine-grain performance control and the people who want safety security and correctness guarantees and this is largely library authors right how like to what extent does the react authors or view or angular have to go through to eke out all the performance and correctness and so they're under tremendous pressures to actually do this and they need tooling that helps them and I think that's likely rust and actually think that web assembly and rust will also end up going to node where you can actually pull in all of these implementations of great rust libraries they're already compiled out to web assembly and it will just work inside of node no more libsass compiling c++ nightmare so here's my closing pitch working with rusts at least in the beginning is like banging your head against the wall but at a very slight angle so that every time you hit the wall you actually make a little bit of progress and at the end you actually look back at this blood-stained wall and you're kind of happy because you built a thing that you didn't think was possible all right here are some links but otherwise thank you [Applause] [Music]
Info
Channel: Coding Tech
Views: 97,043
Rating: undefined out of 5
Keywords: rust, webassembly, web development
Id: ohuTy8MmbLc
Channel Id: undefined
Length: 30min 23sec (1823 seconds)
Published: Thu Nov 21 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.