Getting Started with WebAssembly (WASM) with Rust Lang

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey welcome back in this video i'm going to show you how you can get started creating webassembly modules using the programming language rus now as i said in my other videos where we hand coded a whole bunch of webassembly modules you'll probably never hand code webassembly uh for real live production scenarios and you're probably always going to use a higher level language which would compile them into webassembly now for this reason we're going to look at the programming language for us today but of course there are other programming languages you can use such as go or c or c plus plus or assembly script and we'll probably do some other videos on that at some point but rust is one of those very popular languages and is actually really well designed for creating webassembly modules and as i said in this video we're going to get started we're going to create a couple of webassembly modules we're going to see how that looks we're going to see how that compares to hand coded web assembly and then we'll get that up and running on the back end of node.js and probably in browser as well so with that let's get started [Music] okay so before we get started first thing you need to do is have rust installed on your machine if you've never programmed in rust or you haven't got it installed then actually i've done a video on that already so just go check it out it'll probably appear in the top right hand corner of your screen there and i'll show you how you get started but if you haven't used it before to be honest it's pretty simple uh and it'll be fairly quick to understand even within this video okay so on my machine i've already got rust installed but actually i need to install something else to be able to create webassembly and that is a thing called wassum pack now how i'm gonna do that so if you look at my terminal in front of me is i just need to type in the word cargo which is the package manager for rus very similar to npm and then i type in install and then i just type in wasm dash pack and then if i hit return there then that's going to go and create that now as you can see on my machine i've already installed that so it's going to be fairly quick to install i could use the dash force and that would show you uh what the installation for that would be like in fact why not let's do that already and uh why not so if i just do western pack that is force and then that's going to install that so you'll see it'll take a little bit of time it's going to download a whole bunch of stuff and then take some time and then that will be installed okay so as you can see that's now installed so wasn't packet is on my machine so let me just clear my window for a second and if you are unsure if lanson pack is installed you can actually just type in wise and pack version and if that runs it'll give you it'll be successful by telling you what the version number of western pack is so you can see on my machine it's version 0.10.1 so i have that installed on my machine okay so cool i've got watsonpak installed so the next thing i need to do is create myself a library so because i'm essentially creating webassembly modules i'm not creating a executable program i want to create a library in this case so how i would do that is i would just use a cargo in the same way as i would use npm with something like javascript and then i would say new so i want to create a new package a new library um i want it to be a library so lib so it's dash dash lib and then i just put in the name of the package that i want to create so in this case i want to call it chris dash math and then if i hit return there then it will automatically scaffold up um some packages for me so if i just do an ls here you can see it's created that chris dash math and then i'll just cd into that uh we'll clear that out and you can see it's got a cargo.tml and we've got a source folder what i'm going to do is i'll explain what's in the cargo.tamal in a second but um the first thing i'm going to do now is i'm just going to open up vs code on my machine uh and then we can have a look at some of the code that's generated to do that i just type in code dot in the terminal and then that will launch me vs code so as you can kind of see there i've got this cargo tumble file now the cargo tumble file is very similar to uh a package.json in javascript or in node um so we'll explore that in a second you can see standard things like a gate ignore and again uh a cargo.lock again very similar to a a package.json file in in npm as well so in the source folder that is actually where you're going to create your library that's where your rust code is and then this target folder here is actually where when i built my package that's where the code i'm building gets placed so if i look at this you can kind of see that it's automatically created uh some tests for some rust code so i'm going to delete that because i don't need that and it will create some code from scratch so in order to create some web assembly in rust i need to actually first of all open up my cargo tunnel as i said before it's very similar to a package uh json file that you have with mdm um so you've got this sort of uh area here which is the the package area and you've got chris math is the name version 0.1 and the editions 2018 and of course you can add lots of other things and metadata within there to do that now if you look at the video that i created which is calling roscode from node.js i go into a little bit more details of some of these attributes now what i need to do now is because i want to create a webassembly module rather than a standard ros library i need to specify the type or the crate type for the package that i'm creating so to do that i need to just uh add in lip here and then i just need to say what the crate type is going to be so in this case i want this to be a library that can be called from externally using c style function declaration formats so to do that i need to set that to c d y lib and that's basically saying it's a dynamic library and i'm exposing any functions that i create with there with the c style syntax so any c type application uh can be able to call that and and again in my video calling russ from webassembly i go into this in a little bit more detail so that's what i kind of need to set that for by default i think it's our lib if you want to do rust libraries and call from rust programs but again we're going to be calling it from the outside world because we're going to be creating webassembly modules so once i've set that the next thing i need to do is specify any dependencies that i have so i'll just create dependencies in my brackets here and then the dependency i've got so the package dependency i have is i have this wasn't buying gen uh package that i want to use so i'm just going to set that in here and i can put in the version numbers so it's going to be 0.2.78 um and then we're good we're good to go there and again that's just the the current version there if you look here it gives a little tick um and then it will show you what versions you've got installed locally there but as i said the version that i've got at the moment 0.278 okay so now that we've got our cargo.tml done what we're going to do now is create our code so within our librs file um what we're going to do is create a function that's just going to add two numbers together so to do that in uh rust then functions are declared as fn rather than function so it's just fn and then i would give it the name that i want so i'm going to call add two numbers and then i can accept in parameters so in this case i want to add two new 32-bit integers together and i'm going to call those parameters n1 and n2 so if i just put n1 and then specify that as an i32 and then my second parameter is going to be called n2 and i'm going to specify that is a 32-bit integer again and then i want to return a 32-bit integer so the way you uh declare a return type in a function declaration is basically using a sort of an arrow so that is the minus symbol and the greater than symbol and then i just specify the type that i want to uh return it as so in this case a 32-bit integer which is i32 and then i'll just create my brackets so that i can create the body of my function now in this particular case uh this function would be private if i want to make this public to anything outside of the module then i need to just uh specify it's public by saying hub in front of it so there we've got my uh my function called add two numbers i just need to create my body so i want to add two numbers together so to do that in rust then i would just n1 plus nt now because rust is an expression oriented language then i don't need to specify return it will take the last statement as a return value and i also don't need to semicolon terminate that if however that bugs you for whatever reason if you wanted to and you wanted it to be more of a statement you can do return and then you could semicolon terminate it there and then that would work in the exact same way but as i said russ is a an expression-oriented language so you don't need to necessarily return and you could just do m1 plus n2 and again that expression orientation is really useful when you want to start using more sort of functional constructs weirdly enough with webassembly this is actually kind of closer to when you're hand coding webassembly because webassembly is a stack machine and you're popping things on and off the stack then uh in the same way is rust takes the last statement um webassembly actually whatever is on the accumulator is the last thing on the accumulator um in your function then that is what actually be returned from the function uh in webassembly so it's just something to be aware of when you're hand coding so in some regards this is kind of closer to to webassembly and actually when we look at the webassembly later on the way the rust code is is actually incredibly similar to how web assembly is when you hand code it in webassembly text format and we'll hand code something up in a second but but you can kind of see you know you've got function declaration two parameters supply 32 return 932. it is quite a it's quite a similar syntax in some regards so if you know so to be able to translate between webassembly format and rusty it's not a massive jump okay so we've done that but one of the things we haven't done is specified that this function is basically is something that we want to to put into our webassembly module so in order to do that we have to to specify a webassembly button generation so we do that with a decorator so we would just say um hash and then square brackets wasm underscore bind gen and then that way when we put that on on a decorator function with some bun gen then we know that that is a function that we want to be made available for in the webassembly module uh to be compiled so that's really all we need to do of course you've got these red squig squigglies at the moment because it doesn't know anything about that just now so this is where we have to uh remember that dependency that we created in our our tunnel which was the wasomban gen well yeah it's the exact same thing over here so now that we've sort of decorated that function we're saying we want to generate some some webassembly code with that we we need to essentially uh import that that package and and use that name space uh within that code so to do that we just use use and then we can put the watson bungee in there uh we'll put the prelude in here as well and then i'm just gonna import everything with this star and then oh i've made a little mistake there so it should be wassum underscore by enchant once i've done that then you see the squigglies go away and then we're in a good position so we've now got our code and what we can do now is we can uh build our code and we'll see what that looks like and to build something uh we're going back to our sort of wassum pack cli command so we'll just type in wassum pack and then we would just type in build now there's different targets we can set we can set web no js unknown etcetera for the moment i'm just going to type watson dash pack build and what you're going to see is it's going to fail on my machine and this is probably not going to fail on other people's machine but it fails on my machine because you're going to see this error no pre-built where watsonville binaries are available for this platform unrecognized target and the reason that comes up on my machine is because i'm running uh an apple silicon m1 device so but it tells you what you can do right to disable wassum up so it's the problem is with the wasm opt piece of the bit that optimizes uh your your webassembly modules you you're just basically gonna have to switch that off and then you can uh make it uh available uh later so if i just come back into and do the optimization later so if i just come back into vs code for a second yep and then what i'm going to do is i'm going to disable that uh that wasm optimizer so to do that it's just package.metadata.wasonpack.profile.release and you can see whenever i'm creating a a release target then i want wassum to be off so if i just save that for a second and then we come back into my terminal and now what i'm going to do is run that wise impact build again and you can see that it is now built the application and and it's giving me a couple of things optional fields missing blah blah blah blah not necessary but recommended you you know again you can fill in the metadata for in your cargo tomo file but that is now built so if i come back into my visual studio code for a second and now if i open up this target file you'll see this wasom 32-unknown dash unknown so as you can see there's a release directly directory that's been created and then you'll see underneath that there is a wason file that has been created for me so if we go back into my terminal for a second and we'll just cd into target and then we'll cd into that wasn't 32 unknown unknown and we'll see the into release for a second and then you will see there is that chris underscore so if i do an ls minus la and you'll see that it's created something that's about it's quite it's quite a big file actually so the reason is quite a big file is is it's basically unoptimized at this stage so um it hasn't sort of shaken the tree and removed things like not being used got a lot of debug info etc so it's much bigger than the thing you would actually wanting to be released but you know it's it's kind of there and it's cool and it's generated this wise and fun if i if i wanted to i could look at the what the generated webassembly looks like and the way i could do that is by converting that wasn't file into a webassembly text format so again if you see my other videos you'll have seen a tool that we use when we um take webassembly text format generate uh wasn't files and it's called what to wasm but there's actually another tool which is called the wassum2wac where you can essentially uh convert wasn't files back into webassembly text format now i've got that installed on my machine already if you want to see if you want to learn how to install on your own machine then in my video uh hello web assembly then it shows you how to uh install those the webassembly binary toolkit wabbit uh onto your machine so but we're not gonna do that in this video it's already installed so i'm gonna call the wassum to to what file and then what i'm going to do is i'm going to pass in the the file that i want to create which i'm going to call it chris math dot um awesome and i want to output chris math dot watt so if i return that that will generate me a uh as you can see there across underscore math.what file so that's webassembly text format and then if i open up visual studio code again a second if we open that up we will see what the underlying uh web assembly that it's created so so if we look at this this is really the function um that we've created which is called add two numbers exception two parameters of i32 uh of result i32 and then is uh basically getting those two parameters and we'll hand code this in a second and then we'll show it working um but if you if you do that i'll add the two together um and that is effectively the code that you've got but you can probably see there's a whole load of other stuff going on in fact 1.6 meg of of kind of i i'm gonna say this kind of nonsense that it's generated um it's doing and to be honest don't ask me what it's doing but it's i think basically what's happening is that the generator is creating a lot of stuff for profiling it's creating a whole lot of stuff for more complicated routines so what you're going to see is that it's actually generated quite a large file there now you can optimize this a bit as i said so the way you can the way you can start to optimize is by going back into uh your um into your cargo toma tomo file and then you can start creating um some new uh you know settings within there which will tell you to optimize the release so if i just type in lto equals true what that's basically saying is is optimize the release uh a little bit on build for profile to release do some optimizations there and again if i was to run the build again so if i just actually come back a little bit so we'll just cd back here and then back again that's fine and then if we just uh run the build one more time like we did before it'd probably be easier for me to type watson pat built than uh doing that build that again take a few seconds okay and then if we go back into our target folder for a second osm32 unknown see the release and we'll have a look at the file there and you can see that the the wason file there is is a lot smaller that's been generated and it's kind of closer to uh i think that's about 54k and again if i wanted to i could overwrite that lap file so i could just generate the webassembly text version of that so if i uh run my ysm to what i just run it one more time again um it'll generate a new wac file we'll do an ls minus la uh you can see it's created a new white file there have a look at that it's probably still fairly big from a webassembly text format point of view uh we can open that up you still see it's cut down a little bit but it's still got a load of stuff in there um and again if i wanted to i could optimize even further and remember that optimizer that we switched off then we could basically install that again so what we would uh we could we could run that optimization manually so what i would need to do is install a thing called binary again so if i just type in binary m um that'll install on your machine i've already got it installed on my machine so it should be fairly quick so now that magnetorain's installed if i want to run the optimizer manually i just do a wasm dash opt i do a minus big o z um and then minus o for output so i want an output file called chris underscore math um actually we'll give it a new name we'll call it opt um dot wasom and then i'm going to use chris underscore math.wasm as the file run that and then do another ls minus la and you can see that it's taken that 54k and it's brought it down to uh 44k there so it's given a little bit of optimization uh there and again there are other settings that you can put in there to optimize a little bit further so if i went back into my cargo doctoral file uh under profile to release i could do an opt level i could put that to s or z uh s is telling you to optimize for size rather than speed if i save that again and then if i just did another cargo build it's going to build that for a second and then if i go back into the target folder and then back into the release folder then i stood in ls minus la and you'll see the again it's it's uh sort of still at 54. you know um so it's not really made any difference there but again it's an optimization that you you can kind of make so just play around with the settings and eb but that's basically how you optimize okay cool so we've created our webassembly module and rust as you can see it's fairly simple and again if i wanted to i could create new uh functions fairly easily so if i wanted to create a new function and maybe i wanted to call it something like square and pass in one parameter then i could just have a function called square pass on one parameter called n1 and then i could multiply n1 by n1 and then that's gonna square numbers together so it's fairly quick for me to start creating functions and create new functionality uh off the back of that okay so now that we've created a code all we really need to do is just execute it and see it working so the way to do that is if i come back to my terminal for a second and what we're going to do now is if you remember the ysn pack build command that we had before yeah instead of this is now where instead of not providing a target now what we're going to do is create a target and then in this case we will specify the target is node.js and then that's automatically going to generate all the scaffolding code that we need so if i just type in target node.js and then you see it takes a second there and then you can see in here it says your western package is ready to publish at you know russ play chris math pkj so if i look back in my visual studio for a second you see it's created this uh package folder and and basically what it's done here is created and scaffolded up everything i need to call my add to numbers function that i created there so you can see it's got module exports as two numbers um it's doing all the loading that i need everything i need to do to get this working is is sort of pre-generated for you so that's that's pretty cool um so again if i were to kind of come back to this now all i would need to really do if i wanted to get this running in node.js is create uh an index.js file for a second um and then we'll execute that and then all i need to do is create my new uh library so to do that i'm just going to import the chrismath.js file so i'll just call that uh math for just now i'll put i'll use require for just now so if i'll just do require and then we will put in uh dot chris underscore math.js and that's me sort of uh got my file work in there and then all i need to do to call that is just your console.log and i will do my math.add2 numbers and then i'll pass in the two numbers i want to add together which is 10 and 20 and then that will cancel that out so if i just save that and then if i come back into my terminal and we go into the pkj folder that i just created there and you see the index.js file that we just created and do a node index.js and you can see uh it works so again if i wanted to i could put any other number in there i could put 40. um hit save and then run that again you see it's added that together and again this this sort of works so let me just um let's create a new tab here for a second and then we can go back and mess around with things uh again so if i just come back here we'll build that again like we did before but what i'm going to do now is change my code so rather than just having that two numbers let's have the square function back again so we'll put square that would just be one parameter we'll do n one times uh n1 which is going to be square and then i will re-run my watson pack build so wasn't pac build i'll set that to node.js minus minus target node.js that will build a new version of that package so if we come back into a package for a second uh you can see i've still got my index file that we had before but if i were to open up the chris math you can see it's created the square function now and and again if i wanted to change that so let's rather than adding two numbers together in fact we could that two numbers will still work so we'll do 10 20 and uh 17 that should equal 80. um so if i just run my nodeindex.js you'll see that should still work there which it does but now if i come back into here and then change that so it's doing a square and this time i want to square 10 and then run that again it should come back with 100 which it does so the this is where that target side of things works really well it's it's really easy to create code from russ and then move it uh move it around um and again you can mess around with the optimization you can add new functions and again it's much quicker than hand coding um web assembly um so again it's just something to kind of kind of be aware of for a second it's all that scaffolding for you so it's pretty cool stuff um the sizes because it's got all this optimization stuff it's probably a little bit bigger than than you would do for these simple functions if you were to hand code it um but i think it's kind of pretty cool stuff anyway so um finally the as i said this is this created for node.js bindings if i wanted to if i wanted to create bindings for web then i would do that uh as a website of things and then it would generate me uh my web coding but i i'm not gonna do that just now because you can do that in your own time just change the target to node.js and then it'll create um a whole set of files for you and you're kind of good to go so that is um that is how you get to to use things in rust is it's fairly cool um it's very very quick the only thing i would say is that for simple functions it's they're they're quite big so you know if you think of that wason file that that i created there it's still sort of 45k um i said i was going to sort of prove a point there but if i if i genuinely wanted to create my mo my own math function there so if i just do a cd dot here and then i created a new folder called uh chris math two yep um we'll just do a code if i if i wanted to create my own webassembly hand coded file then i could do it as a web format there and and probably as as you would have seen before um you know to to for me to create something like the the the square function so let's let's uh create something called uh chris math.uh what um all i would be doing is be doing a kind of module and then i could create funk um we'll call that square let's let's make this a little bit uh smaller there i would set my param to be an i32 i would set my result to be i32 um let's make that there for a second and then to make that work i would just do a local dot get zero i'd do a local dot get zero uh and then i would do an i32 mall and then if i wanted to export that out it would just be an export square and i want that to be a function called square so we'll just call that sorry i need to func and then put square in there and and that would be my my my wason file there and again if i if i wanted to convert that from webassembly text format to to a wasm file so yeah this is where my um this is where i had my wabbit so this time rather than doing ysum2 what i'm going to do what to lasso and then what i'm going to do is pass in chris underscore math.what and i want to output that to chris underscore math.wasm and then if i return that there oh no directly i've given the wrong name that's why i did an underscore so let's just move that to a dash and then do an ls one and so so it's created my wason file and and you can see my wason file is 43 bytes right so there's a substantial difference between the code that i've generated for the the wason file uh you know it's it's tiny in comparison to what rust has generated and and the reason is rust is bringing on all this other stuff that it needs to deal with kind of memory allocations and and standardized libraries that it needs to use for other other programs so you know i minus 43 bytes that's 44k there's a substantial difference but of course as you get to larger programs and routines and libraries then that's going to be unnoticeable but it's just something to be aware of is there's a little bit of bloat that's coming with the the rust libraries so it's not really optimized for size and you can kind of see that so you know that was the code i wrote but if i come back into the source file here and we look at the the what that we created earlier so if i come in here and remember we created uh crystalmath.what this is the same code you know this is add two numbers but this is essentially the same code as is as i wrote earlier okay so you know um it's very similar to what i wrote but but as you saw it's got all this other kind of optimizations and junk and memory allocations and stuff that rus uh webassembly might need when you're creating rust programs in general so that you know it it creates it makes sizes a bit bigger so it's just something to be aware of but but the fundamental add two numbers code is is kind of the same there so um anyway i hope you get the sort of uh the differences there as you can see ross is a very cool tool it's a it's a really uh great way of creating webassembly um and then actually start creating larger libraries and stuff then you know some of that below stuff isn't really going to matter the the only thing i would would say there to create stuff from russ as you can see square functions uh you know add two numbers together or whatever it is it's fairly quick whereas as soon as you start getting into more complicated stuff that's where russ is going to come in on its own and where hand coding webassembly doesn't really work out so you need to sort of put your own trade-offs and balances there but hopefully you can kind of see russ is really cool it's a great way of generating web assembly and uh and as you start to get into more complicated libraries to be honest hand coding webassembly is probably just to jump too far anyway uh i hope this has been useful um i hope you understand how to put things together and i will no doubt catch you on the next video
Info
Channel: Chris Hay
Views: 1,049
Rating: undefined out of 5
Keywords: chris hay, chrishayuk, web assembly, webassembly rust, webassembly tutorial, wasm, wasm rust, webassembly rustlang, wasm rustlang, wasm-pack, node.js, javacript
Id: AlsIhnrQO9A
Channel Id: undefined
Length: 33min 10sec (1990 seconds)
Published: Mon Nov 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.