WebAssembly - Tutorial and Performance testing - [AssemblyScript to WASM]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone and welcome to the barely coding youtube channel i am your host daniel bark and in this video we're going to take a look at assembly script and what is that that is a language that tries to resemble the syntax of typescript with of course a few limitations because what it compiles to is webassembly so i think this could be the go-to language for javascript and typescript developers that want to write webassembly we're going to implement a few functions then we're going to verify these functions by writing some tests after that we're going to run a benchmark so we're going to implement the same functions in javascript and then compare the performance to see where we do gain some performance by using webassembly i'm going to see if we can identify some pitfalls because there is a price to pay when you talk between the javascript and the web assembly modules so let's jump into the code [Music] okay so let's see what that init got us we got a new dependency which is the loader that can be used to import webassembly modules we have some scripts so as build untouched that will build the debug version we have as build optimize that will build an optimized release version of our code and if we run just npm run as build it will run both of them we also have some tests and those are located in tests index.js so it's using the node library assert which is a built-in library node imports the module here it tries the add function so that tells me that there should be an add function in this file now so here's the add function so this is pre-compilation so it says this is the entry file of the web assembly module so we have just the add function here we have some config for typescript tells typescript that this is assemblyscript not regular typescript so if we look now in the index.js we see that it it's using loader which is the assemblyscript loader the path is build optimized so this file will use the the release files for now and then it does a re-export it takes the was the module exports and places them on this files exports which means that we can import the webassembly modules from this file so that's what this test file is doing it's going up level importing in that folder which would lead to this file so here it's asserting it's testing the webassembly add one plus two should be three so now i should be able to do npm run tests and it says okay and i think that was correct yeah it said okay we can also do a console log my my module dot add two and two let's see if we get four outputs as well yeah and we do okay cool so we have the build step working and we have the tests working so now let's add another function here now we're going to create a factorial function taking a number again we will return a number this will be a recursive function so we will return if i equals 0 then we return 1 else we return i times we'll call ourselves with i minus one so if three comes in here then i is not zero so then we will go to here with 3 times factorial of 2. second time we will take 2 times factorial of 1. so what this will end up being will be 3 times 2 times 1 and so on if i call this function with three i should get back a six so now we made some changes so now let's do npm run as build again seem to have gone okay so now we can try factorial we'll call it with three and we should expect that to be six and we can do it like this and say add is okay factorial is okay we can do a console log factorial my module dot factorial and three let's run the test so that was okay factorial was returning six and ok great so now we have two functions so now let's start looking at how to benchmark this so we'll do npm install benchmark and let's create a new file call it benchmark.js bench mark equals required and we need to import our western modules so we'll do require this folder that will lead us to the index.js let's set up a suit here run suits we'll pass in the suit so this means the test suit we can console that we started running suit of name and let's say suit on the cycle event we'll set up a callback we get in an event here we'll just console log the event.target chain on another one here complete i'm not sure we can have these as arrow functions because i'm going to use this to access the suit this dot filter for fastest map name one let's start out with our add test and and test so we'll do function and js so this will be the js version of add a plus b and the assembly script version is wasn't lassen.add so let's set up a new test test equals benchmark dot suit call it just add and now we run this test so we do test and we start with the assembly script so we'll just add 10 to 20 and then another one for javascript so now we can do run suit we'll pass in our test and all we need to do down here is call add test let's add the benchmark as a script in here bench mark let's try it out benchmark running ad okay i'm missing something here okay i think it's this now it should work better let's go again now we should see some results okay now it seems to be running to run many times through each of these tested ads okay so now we got the result so the assembly script was called 88 times and the javascript 84 times and then averaged operations per second we see that javascript was a lot faster it was able to execute a lot of more operations per second so we can see when this really simple function runs then the cost of switching to assembly script is a lot higher than what you gain from the actual speed okay but the factorial function in that one we can make the funker function run a lot longer so i think that one should be quite interesting so let's copy this ad test so we'll call this factorial factorial factorial and this one we need to implement factorial call it js js so we have just one in parameter so we do the same we do return i i return i equals zero if one equals zero then we just return one otherwise we return i times factorial js with i minus one okay and let's fix these parameters here we can run it let's run it with 20 and with this one i want to split it up in two tests so i'll call it factorial small small small small i'll do the same for large let's do 20 here and for the small one we'll just do three test large 20 and here we also do test large okay and then we just call a factorial test we can skip add test for now let's run another benchmark okay start with the small one assembly script is done okay javascript came out ahead just a bit so it's 27 million ups per sec versus 35 million ops per sec so javascript won that one if we look at the larger factorial we can see that assembly script was it was an even racing the small one but for the large one assembly script was quite a lot of quite a lot faster so assembly script won this factorial one when we used a factorial of 20 so that's pretty cool so there we could actually make some gain but what i also want to try is what happens if you pass a large payload into assembly script okay let's create a new function we'll call this one square array it takes an array and this is an int 32 array and it returns an int 32 array so an array of the same size will go in and then come out but squared so the length is array.length we'll allocate an array for the result mu int 32 array of length length and now let's start looping so we'll do four let i equals zero i smaller than length i undo plus plus i so we'll take e from array i result i is equal to e times e and then we return result we're now finished with the square array now we need to add some stuff here because we're passing an array between webassembly and javascript so we're going to export some type ids here and you will see why in just a bit but let's do in 32 array underscore id this is what we call the variable and we'll use a function called id all and then in 32 array like this so this will give us the id of that type okay so now we have exported that type so now let's go to where we import the webassembly module so here we're actually going to create some glue code for this function so we're going to create square array here as well where we just take in the web assembly version of square array and we glue it together and we export this version of square array that is calling the webassembly square array version so here we get passed in the array this is the array that comes from our javascript file destruct the square array from the wasm module dot exports we can call it wasm square array we also need some more things we need our type int 32 array id is what we call it now we could do this const result equals square blossom square array so you might think that we could just do this so you might think that this would work but it won't we have to first instantiate an array that is of the correct type so we'll call this typed array so we're going to create a typed array with the correct type so we will import the function new array from here and we'll also import the function get in 32 array so we can use this one to instantiate the array and here is where we give it give it the type id so int 32 array id and then the array that comes from javascript land this function takes the javascript array and the type id returns a typed array we can then pass this typed array into the wasn't square array but in order for this one to come back as a javascript array again we need to wrap this in the get in 32 array like this this is the most complicated part of it but here is where we get the array to match the wasm type and here is where we take the wasm type and make it to match javascript land again now we need to add this square array to our exports here cool let's compile our files npm run as build okay let's write a test for this one square array okay square array and this one we can do one two three four we expect that to be one 4 9 16. and then the strict equals should be deep strict equal deep strict equal npm run test let's see if we need to do any more thing with the types and we get an error here let's see if we need to do this new int 32 array now when i'm running it it says operation requires compiling with export run time so let's add that to our as config to the release export export runtime true okay let's compile it again okay npm run test okay it worked now so let's see if we actually needed this type on this array or if it's happy with just this for the test to pass okay it's not happening that let's leave it like that then cool test pass we can square our array using webassembly now let's do the benchmark so let's copy the factorial one we're taking an array js so let's do the same let's copy this one this one is square array square grade test small is square a small square array assembly script and square array javascript so here we'll do one two three because this is a small one one two three okay let's copy the small test launch march okay now we only need to make this longer okay remove the factorial test and call square array test npm round bench mark okay so for the small one javascript was a lot faster so as we can see that the assembly script had about the same performance in both where javascript lost a bit of performance when the square array was large so let's create a really large array so let's do new in 32 array of length 100 let's fill it with once and then this map val index val plus i times 0.01 and now let's try it with this large array instead so now the test large will be of length hundred okay now it was the difference was a lot smaller let's see if we can make this a thousand okay so we have some interesting results here the interesting thing here is that what we learned from the factorial one is that if assemblyscript would have been able to produce this array or have this array already in memory it would crush javascript in the performance like we see in the factorial test so in this example we can see that there are lots of losses when we're passing this a large array between javascript and webassembly so i'm going to quickly type together the same test but this array is generated on the assembly script side so we don't have to pass the big payload okay so now i created it in this version we just pass in the length of the array that we want so we don't have to pass a large payload between the javascript world and the webassembly world so now let's see what performance we get let's call square array gen test oops let's not run all of them so here we are doing it with 200 elements and in the small test we're doing it with 20 elements so as you can see in the large test assembly script was over two times faster and now we're running the small test in the small test it was still faster but not by as much so as what we can conclude from this is that the size of the payload that we pass between javascript and webassembly matters a lot so what we can learn from this is that the size of the payload that is being passed between javascript and webassembly matters a lot but if we can have the data already on the webassembly side and there are at least a few iterations that are going to be run then webassembly will quickly regain the lost time of switching the contexts this was super interesting the code will be available on github and you can check it out and try it yourself thank you so much for watching if you like the content then subscribe to the channel share it with a friend thumbs up the video and i hope to see you in the next [Music] [Applause] [Music] video [Music] you
Info
Channel: Barely Coding with Daniel Bark
Views: 1,235
Rating: undefined out of 5
Keywords: Javascript, Programming, Coding, Tutorial, Web development
Id: gCT9ebtTzqw
Channel Id: undefined
Length: 25min 51sec (1551 seconds)
Published: Fri May 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.