Introducing Ruvy

By admin
We’ve recently open sourced a project called

Ruvy
PERSON

!

Ruvy
PERSON

is a toolchain that takes Ruby code as input and creates a

WebAssembly
ORG

module that will execute that Ruby code. There are other options for creating

Wasm
ORG

modules from Ruby code. The most common one is ruby.wasm.

Ruvy
PERSON

is built on top of ruby.wasm to provide some specific benefits. We created

Ruvy
PERSON

to take advantage of performance improvements from pre-initializing the

Ruby
ORG

virtual machine and

Ruby
ORG

files included by the Ruby script as well as not requiring

WASI
ORG

arguments to be provided at runtime to simplify executing the Wasm module.


WASI
ORG

is a standardized collection of imported Wasm functions that are intended to provide a standard interface for

Wasm
ORG

modules to implement many system calls that are present in typical language standard libraries. These include reading files, retrieving the current time, and reading environment variables. To provide context for readers not familiar with

WASI
ORG

arguments,

WASI
ORG

arguments are conceptually similar to command line arguments. Code compiled to

WASI
ORG

to read these arguments is the same code that would be written to read command line arguments for code compiled to target machine code.

WASI
ORG

arguments are distinct from function arguments and standard library code uses the

WASI
ORG

API to retrieve these arguments.

Using

Ruvy
PERSON

At the present time,

Ruvy
PERSON

does not ship with precompiled binaries so its build dependencies need to be installed and then

Ruvy
PERSON

needs to be compiled before it can be used. The details for how to install these dependencies is available in the README.

After building

Ruvy
PERSON

, you can run:

The content of ruby_examples/

hello_world.rb
PERSON

is:

When running

Ruvy
PERSON

, the

first
ORDINAL

line builds and executes the

CLI
ORG

to take the content of ruby_examples/hello_world.rb and creates a Wasm module named index.wasm that will execute puts “Hello world” when index.wasm ’s exported _start function is invoked.

To use additional Ruby files, you can run:

Where the content of ruby_examples/

use_preludes_and_stdin.rb
ORG

is:

And the prelude directory contains

two
CARDINAL

files.

One
CARDINAL

with the content:

And another file with the content:

The preload flag tells the

CLI
ORG

to include each file in the directory specified, in this case prelude , into the

Ruby
ORG

virtual machine, which will make definitions for those files available to the input Ruby file.

What makes

Ruvy
PERSON

different from ruby.wasm

Ruby.wasm

Ruby.wasm is a collection of ports of

CRuby
ORG

to

WebAssembly
ORG

targeting different environments such as web browsers through

Emscripten
PERSON

and non-web environments through

WASI
ORG

. Ruby.wasm’s

WASI
ORG

ports include a Ruby interpreter that is compiled to a Wasm module and that module can use

WASI
ORG

APIs. For the Ruby interpreter to be useful in most use cases, it needs access to a filesystem to load Ruby files to execute. While it’s possible to ship Ruby files along with the Ruby interpreter Wasm module and specify in a

WASI
ORG

-compatible

WebAssembly
ORG

runtime to allow access to the directory containing those Ruby files from the interpreter’s Wasm instance, there’s a somewhat easier approach. You can use a tool called

wasi-vfs
ORG

(short for

WASI
ORG

virtual file system) to pack the contents of specified directories into a

WebAssembly
ORG

module at build time. This allows the Ruby interpreter to access the contents of the Ruby files without also having to ship the

Ruby
ORG

files separately with your Wasm module.

Using

wasi
ORG

-vfs with ruby.wasm looks like:

Running one of these modules requires providing the path to a Ruby script for the Ruby virtual machine to execute as a

WASI
ORG

argument. You can see that with the — /src/my_app.rb argument to

Wasmtime
PERSON

.

Pre-initializing

When using a ruby.wasm Wasm module built with

wasi-vfs
ORG

(

WASI
ORG

virtual file system), a tool which takes a specified directory and creates a Wasm module containing a collection of specified files in a specified set of paths, the

Ruby
ORG

virtual machine is started during the execution of the Wasm module. Whereas

Ruvy
PERSON

pre-initializes the

Ruby
ORG

virtual machine when the Wasm module is built, which improves runtime performance by

around 20%
PERCENT

.

Here are some benchmark results from timing how long it takes to instantiate and execute a _start function using

Wasmtime
PERSON

:

Description Toolchain Low Mid High Hello world Ruby.wasm +

wasi-vfs 55.833
ORG

ms 56.262 ms 56.730 ms

Ruvy 44.367 ms
PERSON


44.543
DATE

ms

44.739
DATE

ms Includes + logic Ruby.wasm +

wasi
ORG

-vfs 56.081 ms 56.487 ms 56.932 ms

Ruvy
PERSON


44.449 ms
QUANTITY

44.763 ms 45.216 ms

Execution benchmark results

The “Hello world” example is just running puts “Hello world” and the “Includes + logic” example uses a file that is required containing a class that changes some input in a trivial way.

Here are some benchmark results from comparing how long it takes

Wasmtime
PERSON

to compile a ruby.wasm module and a

Ruvy
PERSON

module from

Wasm
ORG

to native code using the

Cranelift
PERSON

compiler:

Description Toolchain Low Mid High Hello world Ruby.wasm +

wasi-vfs
ORG


1.6351 s
MONEY


1.6590 s
MONEY

1.6844 s Ruvy 439.93 ms

446.31 ms 452.81 ms
QUANTITY

Includes + logic Ruby.wasm +

wasi
ORG

-vfs

1.6227
FAC

s

1.6460 s
MONEY


1.6706 s
MONEY


Ruvy 442.83
PERSON

ms 449.40 ms 456.39 ms

Compilation benchmark results

We can see that

Ruvy Wasm
PERSON

modules take

~70%
PERCENT

less time to compile from

Wasm
ORG

to native code.

No need to specify arguments when executing

Wasm modules created by

Ruvy
PERSON

do not require providing a file path as a

WASI
ORG

argument. This makes it compatible with computing environments that cannot be configured to provide additional

WASI
ORG

arguments to start functions, for example various edge computing services.

Why we open sourced

Ruvy
PERSON

We think

Ruvy
PERSON

might be useful to the wider developer community by providing a straightforward way to build and execute simple Ruby programs in

WebAssembly
ORG

runtimes. There are a number of improvements that would also be very welcome from external contributors that we’ve documented in our README. Shopify Partners who would prefer to reuse some of their

Shopify Scripts Ruby
ORG

logic in Shopify Functions may be particularly interested in addressing the compatibility with

Shopify Functions
ORG

items that are listed.