2026/4/22-24に北海道函館市で開催された RubyKaigi 2026 に株式会社スマートバンクはHack Space Sponsorとして協賛し、登壇者2名を含む計11人で参加しました。今回は参加エンジニアによるセッションレポートをお送りします!

mitani
mitaniからはRyosuke Uchida(@ryosk7)さんの「Extreme MQTT on PicoRuby」についてレポートします。このセッションでは、ryosk7さんが作られたpicoruby-net-mqtt-femtoの設計と内部実装についてトークされました。
picoruby-net-mqtt-femtoはRP2040(Raspberry Pi Pico W)の上でMQTT通信をするためのライブラリです。MQTTはIoTでよく使われる、軽量で高速なパブリッシュ/サブスクライブ型通信プロトコルです。ryosk7さんはシェアハウスで作っていたスマートロックをPicoRubyで実装するために作ったそうです。
RP2040は約264KBという限られたメモリしか持たないため、MQTT通信の機能を実装するのは非常に難しかったそうです。MQTTの全ての機能を載せるのは不可能なため、QoS 1をクリアすること、自動再接続機能をつけること、MQTTSに対応することの3つをGoalとして実装したとのこと。普段Webアプリケーションの開発をしているとあまりメモリ制約に向き合うことはないため、このトークのようにメモリ使用量を切り詰めながら便利な機能を追加していく話を聞くのは興味深かったです。
ryosk7さんがPicoRubyに興味を持ち始めたのはRubyKaigi 2024でのhasumikinさんのトークと、その時にyancyaさんが配っていたRaspberry Pi Picoがきっかけだそうです。今回、スマートバンクでもPicoRubyのワークショップを開いていたため、自分もPicoRubyに興味を持ってryosk7さんのトークを聞きにいきました。RubyKaigiがきっかけで次のRubyKaigiのトークが生まれる循環がすごいいいなーと思ったので、来年のRubyKaigiではどんなPicoRubyの話が聞けるのか楽しみですね。
Extreme MQTT on PicoRuby - Speaker Deck
masawada
masawadaからはasonas(
id:asonas )さんの「From Live Code to Sound: Building a Ruby Live Coding Engine」についてレポートします。この発表では、asonasさんが制作した strudel-rb の内部構造や、その背景が紹介されていました。
strudel-rb は、Strudel の記法を Ruby の DSL として記述できるようにしたツールです。Strudel は、ブラウザ上でコードを書きながらリズムやメロディを組み立てていくライブコーディング環境です。Tidal Cycles のブラウザ版のような立ち位置、といえば伝わる方もいらっしゃるかもしれません。
発表は、Strudel における基本的な概念の紹介から始まりました。そのうえで、Ruby で Strudel のような体験を実現するにあたり、記法をどのようにパースするか、エラーがあった場合にどのように振る舞うかなど、実装上の工夫がいくつも紹介されていました。
発表を見たあと、実際に手元で strudel-rb を試してみまして、できることの幅広さに驚かされました。Claude Code にリポジトリを探索させながら Strudel との機能対応表を作成してみると、実用上欲しくなる機能が広範囲にカバーされていることが分かります。MIDI のインプット機能もあり、MIDI コントローラをつないで操作することも可能です。実際に、手元にあった AKAI APC mini を接続して、ローパスフィルタやゲインを調整しながらライブパフォーマンスすることができました。
先日開催された Gotanda.rb で strudel-rb を実演してみたところ、会場でもとても盛り上がりました。普段あまり音楽に触れていない方でも、実際に触ってみると「これならできそう、やってみたい」と感じられるところも魅力だと思います。
Web アプリケーションやスクリプトだけでなく、このような DSL も作り込むことができるということで、Ruby でできることの幅広さをあらためて感じられる良い発表でした。
kaoru
kaoru からは Ruby コミッタでもある関さん(m_seki)の Programming with a DJ Controller - not vibe coding のレポートをお届けします。1 万円台で買える PC 用の DJ コントローラ DJ2GO2 Touch を PC を操作する HID (Human Interface Device, 入力装置)として使ってみたというセッションです。
DJ2GO2 Touch を購入して一度触って飽きていたところに RubyKaigi 2025 の How to make the Groovebox セッションのリポジトリ経由で UniMIDI という gem を知り、もう一度触ってみる気になった、という導入から始まりました。MIDI とは 1981 年生まれの歴史のある規格で、電子楽器の演奏データを機器間で転送・共有するために使用されています(Wikipedia より)。DJ コントローラは専用プロトコルではなく MIDI のノートのオン/オフやコントロールチェンジをジョグやノブのイベントに使用しています。
デモは 3 本立てでした。ひとつは 2 つの Textbringer を同時スクロールするもので、フォーカスを移さずに異なるウィンドウを操作していました。もうひとつは Pixelmator Pro を AppleEvent 経由で操作するもので、無限回転のノブは累積値、固定範囲のノブは最新値、と分けることでなめらかに操作されていました。ハイエンドカメラの「ダイヤルがいっぱい並んでいる操作感」を Ruby で再現する、という説明がわかりやすかったです。最後の 1 本は Ractor アプリのデバッグに DJ コントローラを使うデモで、N-Queens を位置ごとにワーカー Ractor で並列に解いた進捗状況をログとして MIDI で鳴らす作りになっていました。本来の意図としてはデバッグツールなのですが、出てくる音が思いのほか ambient music っぽく仕上がっていて、そのまま BGM として流していたいようなクオリティでした。
実装面の工夫としては、UniMIDI は便利な反面フロー制御がやや弱く、メッセージが詰まったときに崩れることがあるそうで、MidiM::Treatment というコンパクトなイテレータを導入されていました。また、ジョグホイールを回すと(おそらく) MIDI 側は毎秒数十件の単位でメッセージを送るのですが、制御先の Pixelmator (AppleEvent 越し) や Textbringer (next_tick で実行可能なタイミングを待つ) はその頻度では処理できない/しないため、デバイスの特性(範囲が固定されているスライダーや無限に回転するジョグホイール)にあわせてイベントを圧縮されています。Driq gem のキューを利用してメッセージ送信側(DJ2GO2 Touch)と受信側(各種アプリケーション)の処理を疎結合にしつつイベントを圧縮することでスムーズな体験を実現していました。
ノブの初期値/現在の状態を取る方法は標準 MIDI に用意されていないのですが、DJ ソフトの起動時のやりとりを覗いてみたら SysEx F0 00 20 7F F7 を投げると現在値がまとめて返ってくることを発見したというエピソードが面白く、仕様の曖昧な部分を実際の通信を見て明らかにしていくところはハードウェアをハックする際にあるあるだなと思いました。
家でほこりをかぶっている Novation Launchpad を MIDI や OSC 経由で PC 側 UI に流用することには以前から興味があったので、実際に動く Ruby のコードを見られたのは刺激になりました。私もデバイスを買ったけど飽きて使わなくなりがちなタイプですので、今回のデモ関連のコードが置いてある https://github.com/seki/midim を眺めながら、Launchpad を引っ張り出して何かに使ってみようと思います。
occhi
occhiからはODA Hirohito(@jimlock)氏による 「Back to the roots of date」 についてレポートします。
本セッションでは、Rubyのdateライブラリが抱えているメンテナンス課題と、それに対して「Pure Rubyで再実装する」というアプローチで挑戦した内容についてトークが行われました。特に印象的だったのは、dateライブラリには約10年もの間メインメンテナーが不在であり、その維持がRubyコミッタにとって大きな負担となっているという現状です。
こうした背景の中で、最初に検討されていたアプローチが、「Dateの機能をTimeライブラリへ移植する」というものです。具体的には _parse や strptime といった処理をTime側に寄せていく案でした。しかしこの議論の中で、「そもそも Time.parse のようなヒューリスティックな挙動こそ廃止したい」というコメントがあり、単純に移植するだけでは問題の本質的な解決にはならないことが明らかになります。
そこでODA氏は別の方向に舵を切り、「C拡張で実装されているDateをPure Rubyで書き直せば、よりメンテナブルになるのではないか」という発想に至ります。このアイデアのもとで作られたのが RubyDate というgemであり、AIエージェントを活用しながら段階的にdate_core.c の実装の移植が進められていきました。テストについても既存の test_date.rb を流用していますが、AIが通るテストだけを残してしまうなど、AIエージェントを用いた開発ならではの問題も発生していた点が印象的でした。
実装を進める中ではいくつかの落とし穴とその解決方法も紹介されていました。例えば、DateTime が C拡張の実装に依存しているため、単純にDateだけを書き換えると整合性が崩れてしまう問題や、正規表現の性能差によってRuby 3.2以下ではテストが通らない問題などです。後者についてはRuby 3.3以上をPure RubyのDateを使用し、3.2以下ではC拡張のDateを使用することによって解決されていました。
また、Pure Ruby化における最大の課題はパフォーマンスでした。初期段階ではC拡張に比べて大幅に遅くC拡張版のDateの10%程度の性能しか出ていなかったそうです。そこでボトルネックごとに最適化を行い、さらに「C実装自体も最適化されていないのではないか」という気づきから実装を見直して改善されていました。加えて、AIエージェントに「テストの変更は一切禁止し、C実装の85%以上の性能を維持する」という制約を与えることで改善を進めていった点も興味深いポイントでした。
そして最もインパクトがあったのが、YJITの存在です。最適化を進めても思うように性能が伸びなかった原因の一つが「YJITを有効にしていなかったこと」であり、有効化後は多くのケースでC拡張を上回るパフォーマンスが出る結果となっていました。
一方で、パフォーマンスを追求した結果可読性が大きく損なわれてしまい、本来の目的である「メンテナブルな実装」から逸脱してしまうという課題も生じており、「性能と可読性のトレードオフ」に向き合う様子も印象的でした。
このセッション全体を通して、AIエージェントの活用によってこれまでにないスピードで開発が進められるようになった一方で、最終的にコードの品質や責任を持つのは人間であるというメッセージが強く伝わってきました。ライブラリの実装にとどまらず、これからのソフトウェア開発のあり方についても考えさせられるセッションでした。
Back to the roots of date - Speaker Deck
nissyi
nissyiからは、Tsutomu Katsube(@tikkss)氏による「Portable and Fast - How to implement a parallel test runner」についてレポートします。
どのようなライブラリでもプロダクトでも、コードベースが大きくなれば大きくなるほど、テストも増え、それに伴ってテストの実行時間が遅くなっていきがちです。このセッションでは、Ruby用のデータ処理ツールを提供するプロジェクト「Red Data Tools」で開発されている「Red Datasets」のテストが遅くなってしまったことを発端に、移植性と高速性を備えた並列テスト実行を、test-unitでネイティブにサポートするようになった道のりについてお話しされていました。
OSや使用するRubyの種類・バージョンの組み合わせなど、さまざまな環境での動作を考慮した後方互換性や、移植性・高速性を高めるために取り組んできた工夫について話されているのが印象的でした。
例えば、Unix系固有の Kernel.#fork は使用せず、Windowsでも動作する Kernel.#spawn を採用した話をされていたのですが、この話は冒頭で話されていたこともあり、かなり印象に残っています。関連して、環境固有の事象とオーバーヘッドによる速度を犠牲にすることのトレードオフについて話されており、開発にあたり考えられたことを聞けたのがとても面白かったです。また、「ライブラリがどこを目指していくのか」という想いを大事にしているのだなと感じました。
私は普段、macOSしか使用しておらず、誰かのためにライブラリを開発したこともありません。そのため、環境固有の事象や後方互換性について考える場面はあまり多くありませんでした。今回のセッションを聞くことで、多くの人の利用を想定したライブラリ開発の大変さが垣間見えた気がしています。
yuhi
yuhiからはBenoit Daloze (@eregontp)氏による「Making Hash Parallel, Thread-Safe and Fast!」についてレポートします。本セッションでは、TruffleRubyがバージョン33.0.0にてHashをスレッドセーフ化した背景にあるLightweight Layout Lockについて、デモやベンチマークを交えながら解説されていました。
TruffleRubyとはGraalVM上で動作するハイパフォーマンスなRuby実装です。TruffleRubyはCRubyとは異なりGVLが存在しないため、通常のThreadをそのまま並列実行できます。また、GraalVM JITコンパイラを利用しており、十分にウォームアップされた状態であればCRuby + YJITを大きく上回る性能を発揮します。例えば、セッション中に紹介されたOptCarrotベンチマークではCRuby 4.0のベースラインに対し、YJITで3.5倍、TruffleRuby 34 Native/JVMでそれぞれ8.7倍・11倍のスループットを記録していました。なぜここまで高速化されているかについてはRubyKaigi 2018のキーノートに詳しいのでそちらを参考にしてください。
(セッションの登壇資料より抜粋)
ここからが本題のHashとスレッドセーフ化の話です。CRubyでは、Hashがスレッドセーフであるとは仕様として定義されていないものの、GVLの制約により結果的にスレッドセーフとして振る舞います。一方、33.0.0より前のTruffleRubyやJRubyなどGVLを持たないRuby実装では、Hashはスレッドセーフではありません。並行アクセスが必要な場合はconcurrent-ruby gemのConcurrent::HashやConcurrent::MapなどでRuby実装ごとにスレッドセーフなHashを利用できます。TruffleRubyでは排他制御の実装になっていそうです。一方で、課題としてはRubyGemsやPsychなど主要gemがHashのスレッドセーフ性に依存しており、concurrent-rubyに依存させるのではなく、TruffleRuby本体のHashをスレッドセーフ化することで根本的に解決する判断をしたそうです。
TruffleRubyにおけるHash Storage Strategyを見ていきましょう。Hashは要素数によって内部戦略が変わります。空の状態ではEmpty Strategyでメモリ使用量を最小限に抑え、最大3要素まではPacked Strategyでキーと値のペアを1つの配列に格納します。4要素以上になるとBuckets Strategyとなり、バケット配列と(キー・値への)リスト、そして挿入順序を保持する双方向リストを備える一般的なハッシュテーブルに近い構造になります。そして、マルチスレッドでHashが共有された場合はConcurrent Strategy(内部構造はBuckets Strategyと同一)に切り替わります。並行環境で複数戦略が混在すると複雑になることや、Packed Strategyの最適化効果が薄くなることが理由として挙げられていました。
(セッションの登壇資料より抜粋)
このConcurrent StrategyのHashをスレッドセーフ化するにあたって、バケット配列を同期する仕組みが必要になります。ここでは「並列のRead/Writeはできるだけ通しつつ、レイアウト変更(バケット配列のリサイズやHash#compare_by_identity)は排他的に扱う」という設計がポイントです。MutexやConcurrent::ReadWriteLockでは真の並列を達成することはできないので、Lightweight Layout Lockが導入されました。
Lightweight Layout LockにはRead / Write / Layout Changeの3モードが存在します。Readモードでは楽観的に読み込み、Layout Changeフラグが立っていれば読み込みをリトライします。Writeモードではwriteフラグを設定してLayout Changeをブロックします。Layout Changeモードでは、進行中の書き込みが完了するまで待機し、新しい書き込みも待機させた上で実際のLayout Changeを行います。これにより、バケット配列の同期が可能であることが示されているそうです。
このロック機構により、Hashをスレッドセーフにしつつ並列Read/Writeをサポートしながら、シングルスレッドのベンチマークでもオーバーヘッドなしで実行できるようになった、という点が印象に残りました。詳しくは同氏共著の「Parallelization of Dynamic Languages: SynchronizingBuilt-in Collections」を参考にしてください。
このセッションを通じて、CRubyのHashのスレッドセーフ性やデータ構造などを調査するきっかけになり大変面白かったです。普段使うRubyの裏側の仕組みについて興味を持つきっかけになるのもRubyKaigiの良いところですよね。まさにKaigiEffect!
koshiba
koshibaからはHASUMI(@hasumikin)さんの「Funicular: A Browser App Framework Powered by PicoRuby.WASM」のレポートです。私自身普段からPicoRubyをさわっていて、WS2812のmrbgemまわりでも大変お世話になっているHASUMIさんからPicoRuby.WASMで動くブラウザアプリ用フレームワークのお話がきけるとのことで楽しみにしていました。
PicoRubyはマイコン向けのRuby実装ですが、今回そこに新しく加わったのが、ブラウザで動くランタイム「PicoRuby.WASM」です。HTMLに <script> タグを書くだけでブラウザ上でRubyが動くとのこと。このあたりはruby.wasmとも同じですね。
PicoRubyといえばLチカ。この情操教育はブラウザでも避けて通れないということでデモから話は始まりました。
led = LED.new(id: 'red') while true led.on sleep 1 led.off sleep 1 end
これをそのまま動かしたい…が、ruby.wasmでは sleepでクラッシュ。ruby.wasmにはThreadサポートがなく、Kernel#sleep はOSに依存しているのでブラウザでは動かない。
ところがPicoRuby.WASMでは sleep が動く!PicoRubyはOSに依存しないマルチタスクスケジューラを持っており、PicoRuby.WASMではJavaScriptのメインループ(約16ms周期・60fps相当の setTimeoutループ)がそのままスケジューラの役割を果たす設計とのこと。
sleep は単純な setTimeout ラッパではなく、現在のタスクをサスペンドしてスケジューラに制御を返す(=yield)形になっていて、ほかのタスクに「道を譲る」ことで成立しています。
さらに「デバッグできないと使われない」ということで、Chrome拡張としてbinding.irbが動くデバッガが作られていました。Opalはトランスパイル方式のためエラー位置の特定が難しい話が出ていました。私はクリエイティブコーディングでp5.jsをRubyから使いたくてOpalやruby.wasmを触っているのですが、rbCanvas/p5の記事でもその点に触れられていたことを思い出しました。PicoRubyのランタイム自体をWebAssemblyにビルドしPicoRuby.WASMはこの悩みが解消されていて、binding.irbまで動くとなれば実装が捗りそうです。
そしてキーボードのデモ。
マイコン上のPicoRubyでキーボードを動かしつつ、DRb.start_service を呼ぶだけでキーボード自体がサーバーになる…聞いた瞬間はちょっと理解が追いつかなかったのですが、実際目にしても衝撃的でした。ブラウザ側のPicoRuby.WASMからdRuby経由でLEDの色を書き換えると、リアルタイムにキーボードのLEDが切り替わっていきました!
CRuby(クラウド/サーバ側)+ PicoRuby(IoTデバイス)+ PicoRuby.WASM(ブラウザ)でフルスタックRubyを構成する、という構想が打ち出されていました。なんでもすぐRubyでやりたいなと思ってしまう私にはワクワクしてしまいます。Funicularはそのうちのブラウザ側、特にIoTデバイスのコンフィギュレータ用途を想定したSPAフレームワークです。Virtual DOMを備えたPure Ruby実装で、Reactで書いた三目並べをFunicularで書き直したものと、TODOアプリのデモが紹介されました。 私もまずはFunicularで何か小さなものを作ってみるところから始めようと思います。
Funicular: A Browser App Framework Powered by PicoRuby.WASM - HASUMI Hitoshi - Rabbit Slide Show
いかがでしたでしょうか。来年は宮崎で開催とのことで今から楽しみですね!
株式会社スマートバンクでは、一緒にRubyコミュニティを盛り上げていきたい仲間を募集しています! smartbank.co.jp