Dan Phillips

Deploy Your Next Rails App with WebAssembly (WASM): Smaller, Safer, Faster

This talk focuses on the unique advantages of using WebAssembly (Wasm) for deploying Ruby on Rails applications (yes, on the server). Wasm offers a groundbreaking approach that enables smaller, faster, and more secure server deployments, compared with existing strategies using VMs or Containers

Tropical.rb 2024

00:00:01.920 Here we go! Hi everyone, thanks a lot. My name is Dan Phillips, and today I'm going to be talking about WebAssembly.
00:00:08.920 Who's heard of WebAssembly? Cool, right on! How many of you have heard of WebAssembly on the server? One person? Okay, nice!
00:00:26.840 So, like I mentioned, my name is Dan Phillips. I'm an engineer at a company called Loophole Labs, a small startup that does infrastructure tooling. I live in Chicago, and I also run the Chicago WebAssembly Meetup. I used to help out with the Ruby Meetup in Chicago, so if you're in the area, hit me up!
00:00:50.360 I work on a project called the Scale Function Runtime, which uses WebAssembly as a plug-in framework. This allows you to run multiple languages in the same runtime safely and in a sandboxed environment. I'll talk more about this briefly. Additionally, you can find me on GitHub as 'Dore fill'—just 'Dill' with no space because you can't use underscores.
00:01:11.080 So, what is WebAssembly? WebAssembly, abbreviated as Wasm (technically, it's "capital W ASM"), is a safe, portable, low-level code format designed for efficient execution and compact representation. This description comes right from the specification itself.
00:01:30.759 In the broadest sense, WebAssembly is just another architecture. You can compile things to binaries as WebAssembly binaries. The key differences are that it's virtualized, it needs a runtime to translate to machine code, and that translation step doesn't necessarily mean it's interpreted. You can use it as an interpreter, or you can also compile ahead of time (AOT compiled). There are all sorts of optimizations that convert WebAssembly into machine code.
00:02:00.840 WebAssembly also has a unique role in a client-side technology; most of us know about it through the browser. For example, companies like Google and Figma use WebAssembly to compile C++ image libraries, speeding up their processes. One important aspect is that it provides a safe, sandbox execution environment that makes no assumptions about language or host.
00:02:28.720 Cold start times are another consideration. Who has used containers? Perhaps you've experienced the pain of cold starting a Rails app in a container. Cold start times of WebAssembly modules, which are roughly the same size, can be around one to three milliseconds for not running at all.
00:03:15.920 There's an interesting saying in the WebAssembly community: “Wasm is not necessarily web, neither is it assembly.” The specification doesn't mention the web or browsers, nor does it imply anything about assembly, although there is an assembly-like text format called WAT. The focus of WebAssembly on the server is something I work on quite a bit.
00:03:35.640 WebAssembly on the server is akin to a 'cloud infrastructure penicillin moment.' If you recall the story about how penicillin was discovered by accident, WebAssembly is somewhat similar in that if you look at it closely, it resembles a sandbox that contains code that executes very quickly. It offers a level of isolation that evolves from VMs to containers and finally to WebAssembly, aiming for smaller, safer, faster, and more universal deployment.
00:04:42.840 Solomon Hikes, the creator of Docker, remarked that if WebAssembly and Wazzy had existed in 2008, we wouldn’t have needed to create Docker. This highlights the significance of WebAssembly on the server, which is regarded as the future of computing. Wazzy—the WebAssembly system interface—started in 2019. Although WebAssembly's MVP came out in 2017, many people have been hearing about it for a long time, yet implementation has been slow due to its primitive nature.
00:05:54.919 WebAssembly is essentially just a CPU, lacking an operating system and there are no system calls. Wazzy serves as a system interface modeled after POSIX, the Portable Operating System Interface. It introduces a different security model borrowed from an operating system named Plan 9, which attempted to solve some of Unix's issues but never caught on. The Wazzy standard is still evolving and currently in its preview stages.
00:06:46.279 Let me briefly mention the project I'm working on: Scale. This plug-in framework enables the compilation of various languages to run in WebAssembly, allowing for safe, small, and high-performance plugins. For example, Shopify uses WebAssembly in its Functions runtime to extend its Rails applications.
00:07:14.240 Next, I'll address some challenges of implementing Ruby in a WebAssembly environment. Historically, Ruby requires an operating system and features like dynamic linking and file systems, which have posed difficulties when adapting Ruby to WebAssembly. Recent developments in Ruby 3.2 offer Wazzy WebAssembly deployment through GitHub, enabling users to run Ruby applications with less hassle.
00:08:57.680 One significant challenge was handling errors in Ruby—Ruby’s error handling relies heavily on constructs like 'setjmp' and 'longjmp', which are difficult to implement within the WebAssembly's single stack machine design. Because WebAssembly modules lack context switching, this posed problems for how Ruby handles tasks like fiber switching.
00:09:52.920 The 'Asyncify' project from Mozilla addresses several of these challenges, permitting modifications to the stack and tasks like frame rewinding. While I won’t dive too deeply into this, you can check out Uta Saito’s talk from RubyConf for more details. Moving on, I want to introduce a project called Boxer, which abstracts many technical details to simplify the process.
00:11:30.240 Boxer allows users to take a Dockerfile and output a WebAssembly binary with the actual runtime. It incorporates base layers, virtualized systems, user source code, and imports/exports. Essentially, you can take the latest Ubuntu ster file and utilize it for your projects in WebAssembly.
00:12:13.920 Let’s proceed to a quick demo of Boxer. I’ve set up a simple Ruby app using Ruby 3.3.0. You'll see a little working directory, a basic Ruby application that simply executes a 'puts' command.
00:13:00.440 Now, I can build this just like with Docker. Please ignore any Rust warnings; the build started successfully, finding the base image and compiling everything into a WebAssembly binary.
00:13:49.800 Next, I'm updating the code to show a simple 'hello, world' output. This demonstrates that Boxer makes it simple to work with Ruby applications in a WebAssembly environment.
00:14:16.560 WebAssembly is universal, allowing me to run the same code across different runtimes and browsers. The code I compiled can function seamlessly in any environment that supports the WebAssembly 1.0 spec.
00:15:01.960 In the browser, I've set up a JavaScript proxy server to showcase how it processes a GET request and responds to it through WebAssembly execution. This means the same WebAssembly code can execute in various environments, whether on the server or in the browser.
00:15:47.560 Using WebAssembly in embedded devices can streamline updates since firmware no longer requires complete re-flashing of hardware. WebAssembly allows users to run efficient and safe code without worrying about the physical architecture.
00:17:04.400 However, there are caveats to consider, like the single-threaded nature of WebAssembly, which limits threading capabilities. Yet, projects like 'Asyncify' help alleviate some of this by managing stack switching efficiently.
00:18:13.080 Native dependencies in Ruby raise issues, particularly for libraries like Nokogiri. However, WebAssembly can help package these dependencies into a Universal format, sidestepping many architecture-related concerns.
00:19:00.800 Wacker is another project aimed at managing WebAssembly's native dependencies, providing a structured system for the Ruby environment and preparing it for consistent use across runtimes.
00:19:55.200 Visualizing how WebAssembly enhances Ruby applications can be likened to the difference in size between shipping containers and traditional cargo. Ruby apps can become quite large, while WebAssembly-based deployments significantly reduce that size, leading to faster startup speeds.
00:20:45.680 With WebAssembly deployments, startup speed can drop to as little as 100 microseconds. This is compared to containers which commonly experience startup times in the milliseconds range.
00:21:44.640 In conclusion, the future of serverless functions aligns more favorably with WebAssembly than it does with traditional containerizing approaches, thanks to its lean startup footprint and enhanced security models.
00:22:46.960 WebAssembly is a paradigm shift in how we think about deploying applications and services. Future developments aim to enhance the capabilities and connectivity of WebAssembly, changing the landscape for developers everywhere.
00:23:38.640 Thank you all for your attention!