Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What you can do with Ruby on WebAssembly

Yuta Saito
September 12, 2024

What you can do with Ruby on WebAssembly

Yuta Saito

September 12, 2024
Tweet

More Decks by Yuta Saito

Other Decks in Programming

Transcript

  1. What you can do with Ruby on WebAssembly Yuta Saito

    (@kateinoigakukun) EuRuKo 2024 1
  2. About me • Yuta Saito / @kateinoigakukun • Master's student

    from Tokyo, Japan • Committer of CRuby and Swift • Creator of ruby/ruby.wasm 2
  3. Overview 1. Introduction to WebAssembly 2. Introduction to ruby.wasm 3.

    Showcases 4. Technical details 5. Future vision 3
  4. 1. Introduction: WebAssembly A binary instruction format for a stack-based

    machine Designed to be • Portable • Size- and Load-time efficient • Secure by Sandbox 4
  5. Out side of the web • Many independent runtime implementations

    outside of browsers: • Wasmtime, WAMR, WasmKit, etc. • Easy to embed in applications • Useful for software that accepts untrusted programs from users • Examples: Plugin systems, serverless environments, etc. 5
  6. Both languages and platforms benefit from Wasm • For language

    developers: • If it compiles to Wasm, it can run in various environments • For platform developers: • With a Wasm runtime, it can support multiple languages Good for program distribution formats. 6
  7. 2. Introduction: ruby.wasm • Introduced in RubyKaigi 2022 • Enables

    running Ruby on everywhere by WebAssembly • This project consists of: 1. CRuby interpreter compiled to WebAssembly 2. Packaging system for interpreter + .rb files 3. JS interop library ( require 'js') 8
  8. <html> <script src="https://cdn.jsdelivr.net/.../dist/browser.script.iife.js"></script> <script type="text/ruby" data-eval="async"> require "js" button =

    JS.global[:document].createElement("button") button[:textContent] = "Click me!" button.addEventListener("click") do puts "Hello~" end response = JS.global.fetch("https://example.com/data.json").await puts response.json.await </script> </html> 9
  9. 12

  10. 13

  11. 3. Community showcase • play-ruby ruby.github.io/play-ruby • RunRuby.dev runruby.dev •

    ruby-next playground: ruby-next.github.io4 • Tints 'N Shades gem: hansschnedlitz.com/tints-n-shades5 5 https://www.hansschnedlitz.com/2024/03/25/porting-a-ruby-gem-to-the-browser-with-ruby-wasm.html 4 https://evilmartians.com/chronicles/first-steps-with-ruby-wasm-or-building-ruby-next-playground 15
  12. 4. Technical details 1. Porting CRuby to WebAssembly 2. Package

    Gems 3. Cross-compile C-Extensions 4. Pre-link C-Extension shared libraries 17
  13. 4.1. Porting CRuby to WebAssembly Me: OK, we already have

    C to WebAssembly compiler, so it’s easier than Swift. ! Exceptions, Fiber, GC: NO 18
  14. 4.1. Porting CRuby to WebAssembly • Asyncify instrumentation: • Enables

    conservative GC, exceptions, and Fiber with minimal platform-specific hacks • Trade off performance and code size for portability • It greatly works for the initial stage, but we need to improve it by using recent WebAssembly features. See RubyKaigi 2022 keynote for more details https://rubykaigi.org/2022/presentations/kateinoigakukun.html 19
  15. 4.2. Package Gems Package gem source files into the WebAssembly

    binary by VFS # WARNING: Still Experimental $ bundle add ruby_wasm --group=development $ bundle add rainbow $ bundle exec rbwasm build -o ruby.wasm (snip) INFO: Packaging gem: rainbow-3.1.1 INFO: Size: 51.17 MB 20
  16. 4.3. Cross-compile C-Extensions Cross-compilation support in mkmf • mkmf is

    the core of the C-extension build system in Ruby • 3 major mkmf users (extconf.rb consumers in other words): • CRuby build system • rake-compiler • RubyGems 22
  17. 4.3. Cross-compile C-Extensions Cross-compilation support without trick ✅ Feature #20345:

    Add --target-rbconfig option to mkmf2 https://bugs.ruby-lang.org/issues/20345 $ ruby extconf.rb --target-rbconfig=path/to/rbconfig.rb creating Makefile $ make $ file nokogiri.so nokogiri.so: WebAssembly (wasm) binary module version 0x1 (MVP) 2 Will be available in Ruby 3.4 and later 23
  18. 4.3. Cross-compile C-Extensions Cross-compilation support in RubyGems ✅ PR #7628:

    Add --target-rbconfig option to gem install https://github.com/rubygems/rubygems/pull/7628 $ gem install nokogiri --target-rbconfig=path/to/rbconfig.rb $ bundle install --target-rbconfig=path/to/rbconfig.rb 24
  19. 4.4. Pre-link C-Extension shared libraries Why not static linking? •

    We already support statically-linked C-extensions • But, the build model is not suitable for the RubyGems ecosystem • Take a long linking time (especially due to Asyncify) • Need to tightly integrate with the CRuby build system 26
  20. 4.4. Pre-link C-Extension shared libraries Why not dynamic linking so

    far? • WebAssembly does not have a standard dynamic linking ABI • If we do our bespoke dynamic linking3, the binary will be incompatible with standard WebAssembly runtimes 3 Emscripten does dynamic linking by its own loader 28
  21. 4.4. Pre-link C-Extension shared libraries Breakthrough: Component Model • A

    new layer of WebAssembly standard • Consists of: • WIT (WebAssembly Interface Types) IDL • Module linking • ... and more 29
  22. 4.4. Pre-link C-Extension shared libraries Dynamic Linking upon Component Model

    • Each module has its metadata for dynamic linking • "AOT" linker encapsulates "how to link modules" into Component 31
  23. 4.4. Pre-link C-Extension shared libraries AOT dynamic linking A new

    concept of dynamic linking in WebAssembly • Done at the build time • The final binary is a Component • The linker is originally developed by Joel Dice in wit-component • Adjusted for Ruby use case 32
  24. 4.5. Pre-link C-Extension shared libraries Difference from the traditional dynamic

    linking • The final binary, a Component, contains all the dependencies • No file-based shared library search at runtime • dlopen is available only for libraries known at build-time 33
  25. Summary • Ruby is going to be more WebAssembly-friendly •

    RubyGems support is partially available • Ruby is leveraging the state-of-the-art WebAssembly technology including the Component Model 37