RubyKaigi 2026 キーノートレポート

Charles Nutterさん「Twenty Years of JRuby」
RubyKaigi 2026 2日目キーノート

RubyKaigi 2026の2日目のキーノートとして、Charles Nutterさんが「Twenty Years of JRuby」というタイトルで発表を行いました。

Charles NutterさんはJRubyのコア開発者であり、自身のJRuby開発20周年を振り返りながらJRubyの強みやCRubyとの違い、今後の展望について解説しました。

Rubyとの出会いとJRuby開発の始まり

Nutterさんは1981年に公開された映画「トロン」をきっかけにコンピュータの魅力に強く惹かれ、プログラミングを学び始めました。はじめはBASICを使って簡単なゲームを作ることからスタートし、C言語、C++などを習得していったそうです。大学でJavaを用いたプロジェクトに携わるようになり、その後はJavaのエンタープライズアーキテクト(上級開発者)として活躍していました。

そんなNutterさんがRubyと初めて出会ったのは2004年にワシントンD.C.近郊で開催された「RubyConf 2004」に参加したときのことでした。このカンファレンスではDavid Heinemeier HanssonさんがRuby on Railsを初めて発表する姿や笹田耕一さんによるYARVの発表がありました。

このとき、笹田さんがRavaというRubyで書いたJVMについて触れていたことがNutterさんにとってJRuby誕生の最初のインスピレーションになったそうです。また、Nutterさんはこのカンファレンスへ参加したことで、Rubyの読みやすさと直感的なコードに心を奪われ、とても強い衝撃を受けたと振り返りました。

そして、笹田さんの発表を聞いたことでJVM上で動作するRubyを自分たちで開発できないだろうかと考えるようになり、当時広く使われていたオープンソースプラットフォームだったSourceForge上で初期のJRubyプロジェクトを発見します。そのタイミングでかつての同僚であるTom Eneboさんと運命的な再会を果たし、共に開発にのめり込むことになります。

JRubyの進化とSun Microsystemsへの合流

JRubyのフルタイムコミッターへ

NutterさんがJRubyの開発に取り組み始めた当初はJRubyを使って具体的に何をしたいのかについて明確なビジョンがありませんでした。ちょうどこの頃にRuby on Railsが本格的に普及し始めました。そこで、Nutterさんは大規模Java開発の現場にもJRubyとRailsの組み合わせを導入することに挑戦したいと考えるようになりました。

しかし、そこからの道のりは極めて困難であり、2005年頃のJRuby環境ではRubyのコードがごく一部だけ動作する状態だったそうです。そこから、Nutterさんの挑戦が始まり、まずはJRubyのインタプリタを部分的に書き直すことに着手しました。この改善はパフォーマンスを大幅に向上させることに成功し、2005年のRubyConfでその成果を報告しています。

さらにirbの整備に取り組み、JVM環境でirbを起動できるようにしたうえで、Rails開発に必要なツールの整備に着手し始めます。RakeとRubyGemsの動作環境の構築、ファイル操作や入出力APIの実装、ソケット通信機能やgemパッケージの展開に必要な圧縮ライブラリ(zlib)などの要素を組み込んでいき、Railsアプリケーションを実行するための土台を完成させました。

そして、2006年の春に初めてJRuby on Railsがリクエストを処理することに成功しました。当初は開発モードで検証していたため、動作が非常に遅かったそうですが、本番モードで実行した結果、格段に高速になりました。この成果をJavaのカンファレンスで発表したことがきっかけで、Sun Microsystemsより「JRubyの開発にフルタイムで携わってほしい」と依頼を受け、NutterさんはJRubyの開発を本業とするようになります。

JRubyのさらなる改善

JRubyは20年という長い期間にわたって多くの開発者の貢献とともに改善を重ねてきました。例えば、文字列クラスと正規表現クラスはJavaの文字列や正規表現では要件を満たせず、バイト単位の処理が可能な独自の文字列クラスを実装する必要がありました。そのため、Nutterさんたちは独自の文字列クラスの開発を進め、JVM上でもCRubyと同等の文字列処理機能を利用できるようにしました。

また、Rubyのネイティブライブラリ用のPOSIXソケット(OSレベルのネットワーク通信の仕組み)とPOSIXファイル記述子の動作をエミュレートするため、独自のFFI(外部のネイティブライブラリをRubyから呼び出すための仕組み)の開発をコミュニティのメンバーにサポートしてもらい、改善が前進しました。

OpenSSLライブラリおよびCRubyのopenssl拡張をJRuby向けに移植することで、CRubyと同等の暗号化通信機能を利用できるようにもなりました。

たくさんの改善がありましたが、その中でもNutterさんが長年にわたって取り組んできた主要な開発の一つがJRubyのJITコンパイラです。2008年には、RubyコードをJVMバイトコードに変換する機構をJRubyに実装しました。これによりJVMのJIT最適化が機能するようになり、Rubyコードから高速なネイティブコードを生成できる環境が初めて整いました。Nutterさん自身は「JVMのJIT本体は書いていないが、JVMにバトンを渡す部分を作った」と述べており、これによりJRubyはRuby処理系の中で初めてJITコンパイラの恩恵を受けた実装となりました。さらに2011年にはJVMに「InvokeDynamic」という新しい命令を追加する取り組みに貢献し、JVMがRubyの動的な特性を直接理解して最適化できるようになりました。

別の大きな課題としてFiberの対応がありました。当初は負荷の大きい処理で対応していましたが、2023年にリリースされたJava 21でようやくJVMがFiberと同等の機能をネイティブでサポートするようになり、実用的な速度でFiberが動くようになりました。

このような数々の改善の積み重ねについて、Nutterさんは「Rubyへの深い愛情があったから。JVMが持つ可能性をRubyコミュニティに提供し、RubyをJavaの世界に広めたいという強い思いから続けてこれられた」と語っています。

JRubyの強みとCRubyとの違い

NutterさんとJRubyの歩みを振り返った後、JRubyの特徴について具体的な解説が始まります。

JVMの資産をそのまま活用できる

第一の特徴はJRubyはJVM上で動作する言語であるという点です。

JRubyはJavaが30年かけて磨いた性能・安定性・ツールなどの資産をそのまま活かすことができます。例えばScalaやKotlin、Clojure、Groovyなど他のJVM言語で書いた拡張機能をそのまま使うことができ、なおかつJVMはすべてをまとめて最適化して実行します。

ここで重要な前提として、CRubyにおける最適化の限界について触れておく必要があります。CRubyの拡張機能はC言語で書かれており、JITコンパイラによる最適化はそのCコードの境界で止まってしまいます。つまり、C拡張の内側をJITコンパイラが覗き込んで最適化することができません。一方JRubyでは、コア部分も拡張機能もすべてJVM上に存在するため、JVMが全体をまとめて最適化できます。この違いが、JRubyの性能面における根本的な強みの一つです。

講演では具体的な最適化の事例として、オブジェクト生成の処理について解説が行われました。

Ruby 4.0では、RubyのC実装であるCRubyランタイムに新しい命令「opt_new」が追加されました。この機能の主な目的は、オブジェクトの新規作成(Class#new)処理を最適化することです。その際、CRubyではオブジェクトの割り当て方法をJITに教えるための新たな命令としてopt_newが必要となりました。一方、JRubyでは2016年に同じ目的を達成する類似した機能を実装していました。具体的にはInvokeDynamic命令を使用して、JVMがオブジェクトの割り当てと初期化処理を理解できるようにし、これらの処理をすべてインライン化・最適化することで、優れたパフォーマンスを実現しています。

CRuby 3.4を基準(1倍)とすると、opt_newの追加によってベンチマークで約1.46倍の性能向上が得られました。一方JRubyでは、JVMがもともとこのような高速なオブジェクト生成を得意としており、同様の最適化をより自然な形で実現できています。ガベージコレクタへの負荷も増やさずにオブジェクトを迅速に生成できる点がJVMならではの強みです。ここでガベージコレクタの話題が登場しましたが、JVMのガベージコレクタは非常に高性能で、メモリ不足やガベージコレクタによる処理停止に悩まされることがまずないとNutterさんは語っていました。最適化だけでなく、メモリ管理の面でもJVMの恩恵を受けられます。

また、性能面だけでなくエコシステムの面でもJVMの恩恵を受けられます。JVMエコシステムには世界有数の規模を誇る数十万ものライブラリが存在しており、これらをそのままJRubyから利用できます。講演ではJVM向けのグラフ描画ライブラリ「JFreeChart」を使ってチャートを生成する例が紹介されました。Gemfileに似た形式で依存ライブラリを定義し、専用のコマンドでローカル環境に取得するだけで導入でき、追加の設定やビルド作業なしにそのままJRubyコードから利用できる様子が示されました。

JVMエコシステムのライブラリ活用の可能性を示す事例として、Steamで早期アクセス配信中のゲーム「CROSS THE WORLD」も紹介されました。フロントエンドの描画処理にはmrubyベースのゲームプラットフォームであるDragonRubyを使用しつつ、オープンワールドの状態管理といったバックエンド処理はJRubyで担っています。それぞれが得意な処理を分担する構成で、JRubyのスケーラビリティがWebサーバー以外の領域でも活かされている事例です。

真の並列処理によるスケーラビリティ

第二の特徴は豊富な並行処理機能とサポートが標準で備わっている点です。

JRubyでは単純なスレッド処理が完全に並列化されており、スレッドセーフな可変コレクションを使用することで高い並行性と並列性を実現しています。ただし並行処理は決して容易ではなく、スレッド間で通信を行う場合は同期処理が必須となります。それでもJRuby環境では並行処理が非常に効率的に動作し、安定性も確保されているとNutterさんは解説していました。

講演ではJSONパースの並列処理の比較デモが紹介されました。CRubyでは通常のスレッドを使ってもGVLの制約により並列実行されません。Ruby 4.0で導入されたRactorによってようやく実用的な並列実行が可能になり、Nutterさんはこの進展をとても喜ばしいと語っていました。4コアのMac環境でRactorを使ったデモでは、シングルスレッドと比較して3.7倍の性能向上が得られましたが、ランタイム内部にまだボトルネックが残っており全コアを使い切るには至らないとのことでした。Nutterさんはスレッドローカルヒープの導入やRactorのさらなる改善によって今後大きく向上するだろうと期待を示していました。

一方JRubyでは、特別な仕組みを使わず普通のスレッドだけで全CPUコアをフル活用できます。20コアのサーバー環境では約20倍の性能向上を実現しており、コア数に比例してスケールする特性が示されました。

また、JRubyの並列処理機能を効果的に活用している事例としてログ管理ツール「Logstash」が紹介されました。Logstashは、すべてのアプリケーションから生成されるログを一元管理するためのツールで、高い並行処理機能とスケーラビリティが求められます。これらの要求をJRubyで実現しています。

JRuby 10.1で実現したこと

最後のセクションとして、JRuby 10.1のリリースについて主要機能と今後の開発計画が紹介されました。

コアオブジェクトのメモリ使用量を大幅に削減

メモリ使用量の削減と処理効率の向上という観点から、ユーザーへの影響が最も大きい変更点としてコアオブジェクトの大幅な縮小を取り上げました。オブジェクトが小さくなることでJRubyプロセス全体のメモリ消費が減り、ガベージコレクタへの負荷も軽減されます。

具体的には、JRuby 10.0では32バイトが達成可能な最小サイズでしたが、10.1では内部フラグの格納方法などを見直すことで24バイトへの削減に成功しました。さらに、JVM側の機能である圧縮オブジェクトポインタ(Compressed OOPs)とJava 25/26でリリースされたProject Lilliputの恩恵も加わり、現在主要なRuby実装の中でも最小水準となるCRubyの半分以下のサイズを達成しました。配列に至っては、要素を追加していくとCRubyと比較してメモリ使用量が半分で済むようになります。

64ビット整数の扱いの改善

数値計算を多用する処理のパフォーマンスが大きく改善されました。従来、整数値を表現するためにはオブジェクト本体に加えてさらに64ビットの領域が必要でしたが、JRuby 10.1ではよく使われる16ビット範囲の整数についてはオブジェクトのパディング領域に直接格納できるようになりました。大きな値のサポートは維持しつつ、日常的に使われる範囲の整数のサイズをJRuby 10.0比で半分以下に削減しています。

今後のロードマップ

JRuby 10.1以降ではさらに多くの画期的な最適化が予定されているとして、以下の項目を挙げていました。

  • オブジェクトシェイプの動的進化による効率的なメモリ割り当て
  • 文字列・配列・ハッシュの特化によるメモリ削減
  • スタック経由で引数を渡す方法

オブジェクトシェイプの動的進化を可能にする機能が実装されると、インスタンス変数を保持するために必要なメモリだけを効率的に割り当てられるようになるそうです。Nutterさんはこの実装について、CRubyで採用されている手法から学んでいると語っていました。こちらの機能は今後数ヶ月以内に予定されているアップデートで実装される見込みです。

続いて、文字列については、現在の実装が単一文字のような小さな文字列でも大きなメモリを消費してしまう構造になっているため、文字数に応じた特化型の実装を導入予定です。また、Javaの文字列をそのままRubyの文字列として扱えるラッパーを実装することで、文字コード変換のオーバーヘッドも解消される予定です。配列についても、要素数が少ない場合や整数・浮動小数点数のみを含む場合に特化した実装を用意し、不要なメモリ確保を省きます。ハッシュはキーワード引数のような単純なキー値ペアに対して、ハッシュ全体を割り当てない軽量な実装が予定されています。

これらの改善の基礎部分はすでに10.1に組み込まれており、まもなく本番環境への適用が始まる見込みです。

最後にNutterさんが非常に期待している機能として、スタック経由で引数を渡す方法についての紹介がありました。

オプション引数やキーワード引数がある場合でも、それらを配列に格納する必要がなく、RubyからRuby、RubyからJavaへの引数渡しにおいて、すべてスタック上で処理できるため、オーバーヘッドがゼロになるそうです。

コミュニティへの支援のお願い

講演の最後にNutterさんはRubyコミュニティに向けて協力の必要性を語りました。JRubyを試してフィードバックを送ること、社内でJRubyの存在を周知すること、開発に興味がある人に貢献の機会を提供すること、そして必要であればHeadius Enterprisesの商用サポートの利用を検討することを呼びかけました。

NutterさんはJRubyプロジェクトに20年という歳月を捧げ、コアRuby開発チームの一部のメンバー以外で、これほどの時間をRubyエコシステムの一部に費やしたと言える人はそう多くないでしょうと振り返ります。⁠CRubyとJRubyそしてRubyコミュニティ全体が協力してRubyとJRubyをさらに素晴らしいものにしていきましょう」と語って講演を締めくくりました。

NutterさんのRubyへの愛とJRubyの発展に注ぐ情熱に溢れた素晴らしい基調講演でした。

おすすめ記事

記事・ニュース一覧