Talks

Is it time run Ruby on Web via WebAssembly?

The W3C is starting to recommend to use WebAssembly, and we can compile mruby to WebAssembly very easy in now day. But we have Opal and it works well, we really need to use WebAssembly? Let me share my experience about trying to add mruby to HTML5 game, and discuss the pros and cons when we use Ruby in WebAssembly way in Web.

RubyKaigi Takeout 2020

00:00:00.399 Hello everyone. Today, I want to talk about the easiest way to run Ruby on the web using WebAssembly. This is based on my experiences and the tests I conducted last year, where I tried to rewrite certain applications using WebAssembly and ActionScript technology.
00:00:22.480 My name is elct9620, and I'm from Taiwan. I work as a web developer, and I write a lot of Ruby and Rails code. I've also learned about game development, which is my part-time job. My friend and I have been working together on this.
00:00:34.160 In addition to that, I also work in finance Ruby, helping our classmates worldwide with various projects. My role usually involves creating different projects for my clients, and I'm focused on helping them build their businesses.
00:00:56.399 Before diving deeper, I'd like to share some background on why I wanted to run Ruby on the web. Last year, I discovered an open-source game from Japan that had stopped running for about two weeks. The developers decided to open-source it, and I noticed that the server was written in Ruby while the client-side used Flash. However, as you may know, support for Flash has ended.
00:01:19.119 I began looking for ways to rewrite the client-side code and considered using JavaScript or HTML5. These technologies are closely related to my work experience. I wanted to build a system that could process a significant amount of binary data, but I found working with JavaScript challenging in this regard.
00:01:40.560 My goal was to enhance the client experience for our players by allowing them to use modules to customize their games. To achieve this, I experimented with using WebAssembly and Ruby to create a modular system for our players.
00:02:02.079 Next, I will discuss how to bootstrap a WebAssembly project for Ruby. I’ve attempted to do this several times over the past few years, but last year, I discovered an easier way to load the Android Rack file directly. It only requires defining a configuration and loading Ruby workflow, which allows us to compile Ruby.
00:02:57.360 After defining our custom Ruby configuration, we can create a new compilation target for WebAssembly. I define the compiler to use Emscripten. While I have tried using LLVM, I found it didn’t work well, so I stuck with the Emscripten version to build it for WebAssembly. Compiling with Emscripten requires linking the Ruby binary and our C code, compiling it into a WebAssembly file for our web project.
00:04:08.480 The next step is to add some tags to link the Ruby binary and the necessary files into a single WebAssembly file. I have a demo repository on GitHub that I'll share. In it, you will find a small example project demonstrating how to compile Ruby for WebAssembly. It's straightforward and suitable for use today.
00:05:27.320 I also created a short video to show how to run this project once built. The demo demonstrates how the project works correctly in the browser. I have set up a testing area that allows us to include Ruby code, and when we change the code, we can immediately see the results.
00:06:06.720 However, it's important to note that standard output in WebAssembly is not directly accessible. We have to write some JavaScript to handle it. If we use the Emscripten library, it can facilitate redirecting standard output to the console. In my example, I created a function to capture this output and display it on our webpage.
00:07:03.360 Despite the utility of this method, creating a robust setup requires writing a lot of configuration. As a result, I developed a gem that expedites the process of setting up the necessary Ruby and WebAssembly configurations. This gem allows for a more streamlined experience by utilizing a DSL to specify compile environments, facilitating easy adjustments, such as optimizing the build.
00:08:44.230 I also incorporated a built-in server and auto-recompile commands within this tool, making it easier to construct WebAssembly projects using Ruby. Once we successfully build a WebAssembly project, the next challenge we face is integrating JavaScript with C code and invoking C functions from JavaScript.
00:09:51.439 This is particularly challenging because Emscripten primarily provides a C++ interface for calling JavaScript functions. If you want to call JavaScript functions using C, you will need to define these functions carefully in your C code. We can use external definitions to expose JavaScript functions within the C code.
00:11:05.640 To call JavaScript functions from C, you need to ensure that the function is correctly defined and exported. In this process, we define a JavaScript function that we can call in the C environment by instructing the compiler to expose it.
00:12:45.120 Similarly, calling C functions from JavaScript can be achieved by defining the C function and ensuring it is exposed correctly. However, we need to understand how types are mapped between JavaScript and WebAssembly properly.
00:14:48.400 After setting everything up, running Ruby code compiled with WebAssembly allows JavaScript to interact with it. This opens up new possibilities for using Ruby directly in web applications.
00:15:14.960 Unfortunately, debugging in this environment is quite challenging. We currently do not have effective tools for debugging Ruby code running in WebAssembly; traditional Ruby debugging tools and C/C++ tools like GDB do not work in this setup.
00:16:30.440 One of the main issues I encountered is related to memory management. WebAssembly has limitations on memory size, and if your application exceeds this memory, it can crash, which is problematic, especially when handling large data sets.
00:17:34.240 Additionally, while trying to convert values between JavaScript and Ruby via WebAssembly, there are extensive overheads that can slow down the performance significantly.
00:18:35.120 In conclusion, while it's theoretically possible to use Ruby and WebAssembly together, practical limitations make it challenging. It may work well for specific scenarios, such as educational projects where the overhead of Ruby in a browser is minimized, but for heavy games or applications, practical tools and methodologies are still developing.
00:19:12.160 If you're considering using Ruby with WebAssembly, it may be beneficial for smaller, less intensive applications. It's essential to weigh the potential benefits against the challenges this approach entails.
00:20:06.460 I appreciate your attention during this talk and hope it has been informative regarding the possibilities and challenges of running Ruby on Web via WebAssembly.