Skip to content
sisshiki1969Public

About

Ruby implementation with yet another JIT compiler.

Resources

Stars

141 stars

Watchers

1 watching

Forks

Latest commit

 

History

3,489 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

monoruby

Rust codecov justforfunnoreally.dev badge

Ruby implementation with yet another JIT compiler written in Rust.

What's New

Highlights from the last two months; earlier months are in the changelog, linked at the end of this section.

September 2026

  • Real-application benchmarking drive (ruby-bench / yjit-bench: railsbench, lobsters, fluentd, activerecord, erubi, graphql) with a long run of runtime fast paths: frame-free leaf and Foo.new expansion, machine-code Hash#[] probes, a seeded hash mixer, in-place string/array building, and lazy rubygems boot (#1217, #1240, #1247, #1255, #1261, #1263, #1313, #1365, #1547, #1601).
  • GC work: resident allocation budgets, ~45% faster marking, promotion of leaf object types, prefetching queued marks, and releasing JIT pages and thread heaps (#1238, #1252, #1256, #1259, #1262, #1300, #1466, #1484).
  • JIT and chain-deopt refinement: shared abstract-state frames, polymorphic compare/send handling, method specialization with float registers, and compile-unit-scoped chain deopt, plus a series of ensure/non-local-exit splicing fixes (#1270–#1277, #1326–#1337, #1351, #1363, #1370–#1375, #1664, #1667).
  • Native extensions and stdlib stand-ins: a dynamically loaded mr_* extension ABI with sqlite3 / zlib / zstd / psych / nokogiri moved out of the core, a relocatable install tree, plus Nokogiri (XML, SAX, HTML5, XSLT), Psych over a libyaml port, Prism/Ripper, io/console, the json 2.18 port, and fluentd/lobsters C-extension stand-ins (#1299, #1302, #1304, #1306–#1312, #1314, #1387, #1391, #1393, #1409, #1419, #1649).
  • Encoding overhaul: CRuby's own CJK/ISO/Windows tables, Encoding::Converter with UTF-16/32 and its own object type, regexps in every encoding, and a phased encoding plan with a measurement matrix (#1437, #1463, #1515, #1550, #1564, #1594, #1626, #1629, #1630, #1632, #1637–#1641).
  • Threads: a 1:1 kernel-thread model behind a GVL — signals, fork, JIT/BOP eviction across threads — landed in phases P0–P7 and became the default; Fiber.schedule, Regexp timeouts and per-thread autoload visibility came along (#1443, #1446, #1678–#1685, #1687).
  • ruby/spec and fidelity fixes grouped across Time (zones, exact sub-seconds, strftime), Marshal, ENV, Struct/Data, Float/Rational rounding, Enumerator, and method reflection; the reference CRuby pin moved to 4.0.6 (#1402, #1406, #1412, #1428, #1430, #1436, #1442, #1645, #1659, #1682).
  • aarch64 and CI: aarch64 stub reach past ±128MB and ivar-store fixes, daily arm64 benchmarking, and ZJIT as a third benchmark engine (#1217, #1338, #1415, #1680, #1686).

August 2026

  • Broad early-month ruby/spec compliance drive across Kernel, Enumerator, IO and process handling: Enumerator::Lazy / Product / Chain, fiber-free #each/#with_index internals, ARGF reimplemented in Rust, Refinements, and a full spawn-exec engine with real Data subclasses (#1039–#1065, notably #1046, #1054, #1064).
  • Signal delivery moved onto gated safepoint polls, and the safepoint word was reworked into one process-global, four-byte-lane poll; gc-stress then went opt-in and ran at every safepoint on both arches, catching a string of unrooted-Value and FP-pool bugs (#1070–#1075, #1123–#1125).
  • Hash subsystem overhaul: an AR-mode small-hash table embedded directly in the RValue cell, JIT-inlined accessors ([]=, size, default, …), and correctness fixes for tombstone deletes and iteration order (#1060, #1086–#1108).
  • JIT dispatch modernization: polymorphic call and comparison sites now dispatch through the PIC instead of guarding and evicting, with BinOp/BinCmp lowering unified into one skeleton (#1110, #1127–#1133).
  • Chain deopt became the sole recovery path off a stale JIT frame, followed by a multi-week abstract-state and frame-chain rework (unified joins, outer-frame float promotion across block calls) that got the ActiveRecord benchmark running both correctly and fast (#1134, #1136, #1149–#1168, #1171–#1198).
  • aarch64 kept pace with the chain-deopt work: outlined side-exit islands, branch-range relaxation past the Imm19 reach, and ports of the class-version recovery jump-back (#1153, #1175, #1176, #1182, #1183, #1189).
  • Late-month perf sprint: cached Symbol#to_proc procs, dispatch-free Array/Range scans and equality-by-identity fast paths, plus a JIT correctness fix for inlined send and method_missing dispatch (#1200–#1214).
  • Consolidated the README and wiki into the mdBook documentation site and added this generated Changelog chapter (#1215, #1216).

Earlier months: Changelog (from January 2026), and Progress summary (April 2025 – April 2026) for a prose account of the same period.

Presentation

  • Presentation movie and slides for RubyKaigi2024 is here.
  • Presentation movie and slides for RubyKaigi2025 is here.

Features

  • Written in Rust from scratch. No dependencies on any other Ruby implementations.
  • Fast. Currently, monoruby is comparable to ruby 4.0.5+YJIT/ZJIT on many benchmarks, not just optcarrot.
  • Parses Ruby source with prism, the official Ruby parser (the original hand-written parser was replaced in May 2026).
  • Register-based bytecode.
  • Bytecode executor (virtual machine) emitting machine code directly, for both x86-64 and aarch64 (Apple Silicon).
  • A compact and fast just-in-time compiler with full backends for x86-64 and aarch64. (internally using self-made dynamic assembler monoasm)

Compatibility

Conformance with Ruby has improved dramatically over the course of 2026, driven by an extensive ruby/spec-based compliance effort. Pass rates are re-measured on every interpreter change and published on the project portal: as of commit a13bfe0 (2026-08-31) monoruby passes 97.6% of the core specs (22468 / 23029 examples) and 59.1% of the library specs. As of July 2026 it also passed 100% of the command-line specs and 99.6% of the language specs. Daily-updated pass statistics, compared with CRuby / TruffleRuby / JRuby, are published at rubyspec-stats.

The Compatibility chapter of the documentation breaks the numbers down by category, explains how they are measured, and lists the behaviours that differ from CRuby by design.

Prerequisites

Platform

  • x86-64 Linux
  • aarch64 — macOS on Apple Silicon is fully supported (VM + JIT); CI runs natively on GitHub's Apple Silicon (macos-latest) runners. Linux arm64 works as well.

How to run

See Installation and Build for prebuilt binaries, platform notes, what the build installs, and the full command-line reference.

(1) Install Rust.

Check here to install Rust if you have no Rust yet.

Caution!! only nightly Rust works for monoruby. You do not have to select the channel yourself: rust-toolchain.toml pins the exact nightly the project is tested against, and rustup installs and uses it automatically the first time you run cargo in the checkout.

(2) Clone this repository.

> git clone https://github.com/sisshiki1969/monoruby.git
> cd monoruby

(3) Build and run monoruby with Ruby script file.

> cargo run --release -- test.rb

(4) or, Launch REPL.

> cargo run --bin irm

or

> bin/irm

(5) or, install monoruby and irm onto your PATH.

> bin/install    # cargo install + the native extensions (psych, zlib, …)
> monoruby test.rb
> irm

Using monoruby in GitHub Actions

This repository doubles as a setup-monoruby action (see action.yml), modeled after ruby/setup-ruby. The ref after @ selects the monoruby version to install:

steps:
  - uses: sisshiki1969/monoruby@master # or a release tag
  - run: monoruby my_script.rb

The action first tries to download a prebuilt binary attached to a GitHub release (built by the release binaries workflow), which installs in seconds: release tags use their own release's assets, while @master / @nightly use the rolling nightly prerelease, rebuilt on every master push (so it can lag a just-pushed HEAD by one build, ~15 min). Automatic builds cover x86-64 Linux only; assets for Linux arm64 and macOS arm64 are published on demand by dispatching the release binaries workflow with the wanted tag and targets. When no asset exists for the ref/platform — or prefer-prebuilt: 'false' is set — the action falls back to building monoruby from source on the first run for each monoruby revision × runner OS/arch and caches the resulting binary and runtime tree with actions/cache, so subsequent runs restore in seconds. Linux (x64/arm64) and macOS (Apple Silicon) hosted runners are supported either way.

Inputs and outputs:

Name Kind Description
prefer-prebuilt ('true') input Set to 'false' to skip release assets and build the exact ref
cache ('true') input Set to 'false' to disable the source-build cache
cache-version ('v1') input Mixed into the cache key; bump to discard existing caches
prebuilt output 'true' if a prebuilt release asset was used
cache-hit output 'true' if the built binary was restored from cache
monoruby-version output Output of monoruby --version
ruby-version output RUBY_VERSION reported by the installed monoruby

Benchmark

Up-to-date benchmark results (yjit-bench, re-measured on every interpreter change) and the ruby/spec compliance dashboards are published on the project portal. On the x86-64 run of commit a13bfe0 (2026-08-31), over the 59 benchmarks that completed on both interpreters, monoruby averaged 1.28x the speed of CRuby+YJIT (geometric mean).

The Benchmarks chapter of the documentation explains the measurement methodology and how to reproduce a run locally. The numbers below are older one-off measurements, kept for the record.

1. Optcarrot benchmark

Several Ruby implementations described below were measured by optcarrot benchmark. See Benchmarks — optcarrot for details.

Versions of used Rubies

  • ruby 3.4.0dev (2024-04-27T08:56:20Z master 9ea77cb351) [x86_64-linux]
  • truffleruby 24.0.1, like ruby 3.2.2, Oracle GraalVM JVM [x86_64-linux]
  • truffleruby 24.0.1, like ruby 3.2.2, Oracle GraalVM Native [x86_64-linux]
  • monoruby: 3e348afd4141c40978342e67ad26d42dc0b8d2a7

Optcarrot benchmark

optcarrot_benchmark

Optcarrot fps history (0-3000 frames)

optcarrot_fps_history

2. Other benchmarks

Several Ruby implementations described below were measured by yjit-bench. See Benchmarks — yjit-bench for the raw data.

Versions of used Rubies

  • monoruby: monoruby 0.3.0
  • yjit: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [x86_64-linux]
  • truffleruby-24.1.1: truffleruby 24.1.1, like ruby 3.2.4, Oracle GraalVM Native [x86_64-linux]

Results

The graph shows the speed ratio against truffleruby. (higher is better)

micro_bench

About

Ruby implementation with yet another JIT compiler.

Resources

Stars

141 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages