GothamGo 2019 – "WASM: Bringing Go to the Browser (and Beyond!)" by Gabbi Fisher

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] thanks for the introduction my name is Gabi Fisher and I'm a systems engineer at CloudFlare today I'm really excited to talk about ghost supportive web assembly and how web assembly will let us run go in browsers and other cool environments I'll first start out my talk by discussing where we commonly run go as well as places where we haven't really thought about using go I'll then introduce web assembly and what exactly it is I'll go over the Go wasum tooling that's now provided as part of the go language I'll have some demos of cool web assembly and go applications and then I'll conclude by discussing the path forward for go and web assembly so when I think of Gophers I always subconsciously think of Wales and that's because go and docker in my mind go together very closely when I deploy code that's written and go it's often in a docker container and indeed the go development cycle that a lot of us are familiar with involves building your go code into an executable having that executable around so you can put it into a docker container as a service and then running that docker container on an orchestration framework like kubernetes the underlying assumption here is that go is something that we naturally just run on servers and go is a really popular back in language we often use it to write back in services api s and other back-end tooling this does beg the question though why haven't we tried running go elsewhere is it because we can't put go in other places where can't go actually go one place where go was not easily deployed is the browser environment and other JavaScript environments in general browsers have been the land of JavaScript for over a decade now and the problem with JavaScript for a back-end engineer like me is that it tends to be quite distinct from the languages I'm really familiar with event based programming is not easiest thing the map on top of concurrency based programming as a systems engineer who recently had to write JavaScript for a project I found learning JavaScript to have quite learning curve in many of its concepts like promises were very unfamiliar to me it was honestly kind of telling when I learned that one of the back rooms for NPM is nothing prevents misery that was honestly my mood as I taught myself javascript and got through that learning curve and I just thought myself thinking what would have mics what about of my experience have been like if I had run go in the browser instead of having to use a language and really unfamiliar with there is some tooling that lets you run go in what is a JavaScript environment that includes the transpiler go for Jas the thing is that when you're transpiling go to javascript you'll lose some of the performance benefits and other other runtime goodies that you get from go usually so I was thinking what if there are a way to actually run compiled go code in JavaScript instead of having to turn it into JavaScript before executing it this is where web assembly comes in web assembly is a binary instruction format that is meant to run on browsers agnostic of whatever architecture or operating system the browser is on top of as systems nerd I'm also really excited about web assembly because I think it's a really big stride it's the first binary instruction format to be introduced and actually used in production in the last 30 years and web assembly was designed to take away some of the lock in x86 and arm introduced when running code since you had to compile for individual targets that oftentimes couldn't go across different operating systems webassembly can be run in all major browsers at the moment so this includes Chrome Firefox Safari and Microsoft edge this means that theoretically any language that can compile into web assembly can be run on any of these popular browsers so if Co has support for web assembly that could be the answer to my question I could run go on the browser and it is actually the case that with go 1.11 there's actual support for running go as web assembly so now we can actually let the the gopher out of the box or the container and run it in environments that we previously hadn't entertained like the browser the tooling introduced we go one point eleven includes a new syscall j/s library that helps us write go code that is meant to interface with javascript environments it also includes a compiler target so we can compile or go into web assembly and finally it includes some wrapper functionality that we can't access as a javascript file to help glue our go compiled in the wasum and our javascript environment together so we can run go in that javascript environment before I get into examples of these new features I just want to provide a disclaimer that go wasum support is still considered experimental meaning that you can expect to see a lot of changes to go wasum in upcoming go releases and some of these changes could also be breaking changes that make the examples I'm going to share today possibly broken in the future so let's get started with this syscall package sis called j/s allows us to call javascript from go but it also allows us to expose go functions to JavaScript I'll first cover an example where we're using syscall j/s to access javascript and perform JavaScript functionality in go code so in this case I can actually get JavaScript variables from the document object model that we often see on webpages I am getting the Dom and I can also call elements on the Dom class including get or Eckankar functions on the Dom class including get elements by ID and what get elements by ID does is it takes the ID I pass in as the argument and it returns to me the actual element and go so I have in this hello text variable is now the element in JavaScript for hello text I can then call set functions on this element include and then change fields in that element to a particular value so I can access the inner HTML field of the hello text element and change it to say go was here because go was indeed on this web page to take a cue from Missy Elliott we're now going to flip it and reverse it and we're going to expose go to JavaScript and see what that type of deployment looks like to call go from JavaScript we first need to define a function we'd like to expose in this case I'll work on a simple add function that takes a list of JavaScript numbers sums them and returns the sum to JavaScript an important step is making sure that the function I seek to expose has this function signature this is required this function signature makes sure that we can access fields from a JavaScript class if this function becomes part of a JavaScript class so those fields would be passed in through the this parameter next we have to make sure we can also pass an arguments to this function be exposed so I take JavaScript values in a list as my arguments and finally the return type for this function has to be an empty interface meaning we can return anything I honestly would prefer if it required us to return a JSO we have that symmetry between taking JavaScript arguments and taking and returning a JavaScript value but there's a wrapper function we'll talk about later that automatically turns the output into a JavaScript value so now that we have an array of JavaScript numbers passed in we're going to iterate through that array and we need to convert all of those elements in the array which are JavaScript numbers and to go integers so we can actually apply go methods to it so that's why I'm calling int here and once I've iterated through all of the numbers in this JavaScript array turn them in the int and sum them I return that sum but I make sure to call value of beforehand to ensure that the sum I'm returning to JavaScript is in a JavaScript type and it's not left in a go type now to expose this function that we've written there are a couple more steps the first of which is that we take this go function and we have to turn it into a JavaScript function type that's why we call J's funk of on our add function func of is the wrapper function I mentioned earlier that converts your return type from add into a JavaScript type for you so that's implicitly done but I prefer to do it explicitly for the sake of clarity now that we have a variable add func that represents the JavaScript function that we've turned out into we use a setter like in the previous example to set the add variable in our JavaScript environment to equal that add function that we turned into a JavaScript function we also should free memory used for go functions and variables on the heap and you're probably wondering why I have this channel set up this channel is an empty channel that is read from but never written to and that serves to keep this main function alive if you want to expose a function from go to JavaScript the go binary must keep on running specifically this main function was to keep on running because if this main function exits you might find yourself in a situation where your JavaScript code tries to call add and finds the add is undefined because it's no longer been set to equal add func as it was and go so we have to keep the scum main function alive there are a couple of ways to do this that aren't as exotic as using channels this is just what I see in a lot of go waz them in the wild you can use a weight group if you want and Philippe I mentioned you can even use an empty select to keep this main function alive now that we've done all of this work to set up our add function on the go side calling it from JavaScript is actually pretty easy we can access it and use it like a function we wrote in pure JavaScript there's a little more setup we need to do before we can actually run this program like this so ever and that involves the walls I'm exec file and I'll get to that very soon now that we've written go code that is built to interface with JavaScript we actually need to compile it into web assembly and this is where the new web assembly target comes in invoking it is really similar to compiling go for any specific operating system and architecture in this case you're just passing in j/s says your operating system and wasum as your architecture and with that you get your walls in binary now that we have our walls in binary we just need to make sure we glue our wasum and are calling javascript code together correctly and this is where while some exec is useful while some exec is a file you find in the actual go language it's under a misc wasum and its core purpose is to expose a go class in JavaScript that you need to initialize in your JavaScript code you only need to import this file and explore and use the go class from it to set up all of the necessary glue code between javascript and go but I'm going to look at the scope class with a little more detail just so you know what's really going on under the hood the scope class has three tasks its first is to actually let you specify your configurations for the runtime you'd be starting and your goal wasum code this lets you pass in runtime variables like go debug it also does things like graceful error handling when your goal was on binary exits so in this case it's taking an exit code and it's nonzero it'll actually properly login to your console for you so that can assist with your debugging next the go class also provides a field called import object an import object is very important because it provides JavaScript side functionality for interacting with JavaScript variables and correctly passing them into go and vice versa this function here called J s value set is actually invoked by the sis call j s set function i demonstrated earlier had this function not been included in the import object some of our siskel JS functions in our wasn't binary simply wouldn't work another example of glue code between javascript and go that's handled by import object or specified an import object is logic for making sure that when you call log printf and go that's actually treated as a console log statement in JavaScript so if you want the C output our log output from your go binary it can actually be funneled into console log and treat it as if it were part of your JavaScript that's all handled to in this field finally this class also exposes a run function and this run function takes your web assembly instance and actually starts it it handles setting up global memory references between your JavaScript and your go code and it also maintains state like whether your was and binary has exited or not to revisit our add function now that we know a little more about how to use it while some exec let's go over how we actually use the go class to expose the add function we wrote earlier first we have to instantiate this go class and then we need to call a worker application or a worker function called webassembly dot instantiate streaming to load our wasum binary as well as pass in our import object glue functions once we call that we get our loaded webassembly instance and then we call go run on it once this setup is complete then we can call our add function and compute our sum as if it were part of native JavaScript with that I'll give a quick demo of a fun application I built with go and wasum this demo is one that has us take a JavaScript byte array that represents an image turn it into grayscale and go and then return the grayscale image as a JavaScript byte array so it can be displayed on a web page in this case I'm taking advantage of the optimized image library and the ghost standard library to apply this transformation so on the left side here we have our image our function that takes our JavaScript input which in this case is a JavaScript byte array and then converts it into a go byte array or a byte slice in this case and passes it into a helper function applies the image transformation then we take the transformed image bytes which are a ghost slice and we take that byte slice and turn it into a JavaScript byte array once again using the J's typed array of function once we've converted those transformed image bytes into its proper go type we return it on the right-hand side I expose this gray image function with the exact same logic I used to expose the add function earlier so there's an image oh wow this place here but not my laptop fascinating so you can see that I'm running this on a simple local server the Wazza has been initialized and i provide a simple HTML page that lets you upload a file apply transformation to it so we have a nice gray scaled calico cat and we can continue invoking this exposed to go function to other images as well so now we have this grey cat that's staring into your soul so something you might have observed here is that that code was executed really fast browsers are built to load third-party code as quickly and efficiently as quickly as possible and run it as efficiently as possible because people want a seamless browser experience when they download content from the internet that is dynamic they want it to run in front of their eyes with no pause this is partially because browsers use an architecture that doesn't rely on containers instead they have a whole separate set of engines that are used to run this third-party code in a fashion that's like go routines versus processes it's a lightweight way to run untrusted third party code whereas containers are kind of like processes in this case they provide a lot of isolation and sandbox ink but there's a cold start that takes a lot of time before you can actually see your code in action this then brings up the question this sounds like something that would be really useful in servers especially if we want people to be able to run third-party code quickly and in a world where functions as a service are becoming extremely popular it sounds like this is a cool way to leverage wasum to build a whole new class of function as a service products this is where I get to the beyond the browser part I promised in my talk title fast baws I'm loading and execution is why companies like CloudFlare and fastly are thinking of using web assembly execution as the future of functions as a service and especially to compete with pre-existing offerings like AWS lambda functions GCP functions and Azure functions which all rely on containers to run third-party code CloudFlare workers and fastly loose it are two examples of projects building this Waze them on the server ecosystem this is a really simplified chart that compares the stack necessary to run third-party code in a container function as a service versus running third-party code in a woz and based function as a service implementation because container starts can take up to 500 milliseconds being able to remove that layer from a function as a service offering like cloud floor workers enables us to get rid of up to half of a second of latency of a running third-party code that being said there's still some performance benefits we can continue to squeeze out of using Lausanne and one of them is the fact that Waze them at the moment bundles an entire language runtime into each executable in starting that runtime takes time that could be factored out if we had a shared runtime between different go wasum executables this is one of the core questions that is facing wasum as we continue to develop it and my colleague Ashley Williams has some really interesting thoughts on this one approach to this is taking that runtime out keeping it running and accessible to all of the third-party applications we're loading on a Wazza environment and then making sure that we can just have a bunch of different laws and applications share that runtime instead of starting it up individually I'll provide a click a quick demo of using the same grayscale code on a CloudFlare worker so I can create an endpoint that lets us apply grayscale transformations to whatever image we like so here I'm actually uploading my worker script and I've exposed it on my domain I have Gabby dot fish which I'm really proud of and I called a grayscale endpoint I pass in an image domain and path as an arc is a parameter this image domain and path is always requested over HTTP I guess I hope that's how we're all requesting things these days and I get a grayscale version of this kitten and it was pretty snappy so it is if there's another cute kitten there so I think that's an example of where using wasum as the basis for functions as a service is opening up a whole new world for running third-party functions on the Internet you're free to try out that endpoint for yourself if you'd like it's still alive I'll just learn you that one of my co-workers messaged me saying like you're the third largest user of workers CPU time at the moment like what are you doing if you if you use my endpoint you can make me number one and that would be really interesting for him the same I so I'd like to use goal awesome for using go functionality that is otherwise inaccessible in a JavaScript environment I also like go awesome because it lets us take advantage of these new functions as a service offerings we're seeing more of on the Internet and there are other reasons to use go wasum a recent situation where I found myself very thankful for gold awesome was when I had to deploy a entire go package on a worker and it's kind of hard to imagine rewriting this entire set of logic in JavaScript because hey this is a lot of files but be if these files used a lot of go constructs like like sync Maps and that's something that's really hard to translate to JavaScript event based programming so I was able to just compile this into a go wow some worker and deploy that instead of thinking about rewriting code and another thing that's nice about maintaining this consistency maintaining a go code base is that we can envision a future where client-side and server-side go code or both go and we can share all of the structures and functions we'd like between our client and our server instead of having to write the client in JavaScript since go blossom is still in development there are a lot of opportunities to contribute to the space and make go azam more efficient and more easily usable here are a couple of things I think need to be developed before go azam is something that any go engineer feels ready to use first of all best practices for writing go waz them are still relatively unknown I don't know if I'm supposed to call JavaScript and go or if I'm supposed to expose go to JavaScript it'd be nice to have something like the rust waz and bind gen book this is a book that provides best practices for rust wasum and to have that and go would help clarify how exactly we should be using go and web assembly next the memory usage and go azam tends to be quite inefficient at the moment as of go 1.12 and pretty sure it still asks for a gig of memory by default which is massive - imagine asking your browser for or a massive to run in a worker there's been some work towards cutting that required memory down to 16 megabytes as well as implementing garbage collection so we can continue using a small slice of heap memory to run our goals them instead of asking for a huge amount of it that never is garbage collected there are some branches of NGO that already accomplished this Devin Mullins that Google worked on a really cool one that I've adapted it for my own uses so I'm happy to share that with you if you'd like to check it out and finally since entire runtimes are loaded into go Watson binaries that doesn't mean that go wasn't binaries are only slow to start up but relatively slow start up still much faster than containers which is great it also means that our go balls and binaries are really big that could be a bit of a burden if you're downloading that over the Internet and it also just makes for large uploads to services like workers or fastly loose it I hope this talk encouraged you to think about using go beyond just servers but also to put it in your browsers as well let's try it on some of the new serverless platforms we're seeing I also encourage you to think about contributing to go wasum on goal in the golang repository because this is something that's still under active development and I think is a really exciting place for folks to get involved with contributing to the go language and finally I hope you're excited to play with go awesome and I'd love to see what you build with it thank you so much [Applause] [Music] you
Info
Channel: Naut Human Productions
Views: 3,564
Rating: 5 out of 5
Keywords:
Id: oVzFNktAkvA
Channel Id: undefined
Length: 26min 47sec (1607 seconds)
Published: Sun Jun 16 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.