ITエンジニアが参加した「ながらRuby会議01」で得た成長のヒント

はじめまして!株式会社スタメンでバックエンドエンジニアをしている ちぇる と申します。 この度、2025/9/6(土)に開催された「ながらRuby会議01」に参加しました。

会場は岐阜県の「うかいミュージアム」で、自然に囲まれた素敵な場所でした✨

近くには金華山(きんかざん)があり、山頂に築かれた岐阜城が見えます🏯

いざ、会場へ!

まず驚いたのは、 今回開催された「ながらRuby会議01」でしたが、なんと応募はほぼ満員...! 東海地方にも、これだけ多くのRubyistが集まり、熱量を持って交流できる場があることに感激しました。

ちなみに、nagara.rbは、今回の「ながらRuby会議01」で記念すべき第100回目の開催だそうです。Rubyコミュニティを作ってくれた先人たちに感謝です。

アフターパーティーでは、皆さんと鵜飼に参加しました✨

以下、実施されたプログラム内容となります! ふむふむ。ジュニアエンジニアの自分にとって、目の前に Ruby のアタラシイ世界が広がっているぞ...🤔

regional.rubykaigi.org

この記事では、特に気になったセッションについてご紹介させていただきます。

refinementsのメソッド定義を4000倍速くした話

スピーカー:alpaca さん(@alpaca_tc

speakerdeck.com

社内で Ruby をアップデートしたところ、どうやらアプリケーションの起動やファイル変更時における反映が遅くなってしまったようです。 そのため、 vernier という gem を使って実際に速度を計測します。

すると、Ruby3.2 と比べて Ruby3.3以降では、Module#refine を呼び出すタイミングで、なんと実行時間に4000倍以上もの差分が見られたそうです👀(計測

Module#refineとは、簡単にいうと「モンキーパッチを安全に使うための仕組み」です。

例えば、以下のように書くと、String 全体に shout メソッドが定義されてしまいます。

class String
  def shout
    self.upcase + "!"
  end
end

"hello".shout   # => "HELLO!"

しかし、refine を使うことで、モジュール内での定義にスコープを限定することが可能となります。

module StringRefinement
  refine String do
    def shout
      self.upcase + "!"
    end
  end
end

using StringRefinement # こちらを実行した場合のみ有効に!

"hello".shout  # => "HELLO!"

では、この refine がなぜ遅くなってしまったのでしょうか...? ここから原因調査に入ります。

調査を続けていくうちに、rubyリポジトリ内で rb_clear_all_refinement_method_cache(); の処理が追加されたことが判明します。

これが怪しいのでは...?👀

そこで、実際に Revert パッチを当てて確認すると、なんと速度が改善されました🎊 (再現

つまり、Ruby3.3以降では、refineに関連する callcache の無効化処理が追加され、それによってパフォーマンスリグレッションが起こってしまったのですね。

callcacheとは「同じメソッドを再度呼び出すときに、以前の呼び出し結果を再利用する仕組み」のことです。 PR にあるように、refineに関するキャッシュによるバグが発生してしまったために、このキャッシュを使用しない変更が反映されたんですね。

Rubyでは、メソッドを実行する際、継承チェーンに沿って順にメソッド定義を探します。 しかし、今回の alpacaさんのケースでは、ObjectSpace になんと、70億のオブジェクトが存在したそうです...😳 そのため、refine 関連のメソッド探索がキャッシュされない場合、相当のオーバーヘッドが発生することは想像できますね...。

そこで alpacaさんは、refine callcache 専用の格納先を用意する方針で実装することにしたそうです。 しかしご存知の通り、Ruby は C言語で書かれています。そのため、上記の方針をC言語で書いて実現する必要があります。 Rubyistにとって、なかなか大変な作業だと考えられます...。

alpacaさんは案の定、C言語特有のGC(ガベージコレクション)によるメモリ管理や、セグメンテーションフォールト(不正なメモリアクセスを行ったときに OS が強制終了させるエラー)等に苦戦します。

しかし、それらにもめげず、ChatGPT や rubyhackchallenge を駆使して、ついにマージまで実現したそうです!🎉(改善) すごいですよね。

該当PR: Optimize callcache invalidation for refinements

ここから、alpacaさんは以下の教訓を話されてました。

  • パフォーマンス改善の流れは同じ(計測 → 再現 → 改善)
  • AIやコミュニティの助けを得て貢献できる

また、alpacaさんは以前に RubyKaigi にも参加されており、GC やセグフォについても学んでいました。こうした知識が、実際の現場で活かせることを実感されたそうです。

TUNAGのモノリスとアーキテクチャ

また、スポンサーセッションとして、弊社の近藤(@sei_kondo97)も登壇しました!

弊社は、現在 TUNAG というエンゲージメントプラットフォームを提供させていただいております。TUNAGはモノリス構造のシステムですが、年々サービス内容が肥大化しており、今後はサブサービスやサブアプリケーションに分割し、各ドメインごとに分けて管理していく方針となります。

最近では、「TUNAG本体」から「TUNAGチャット」が分離されました。また、「TUNAG本体」を認可サービスとして利用することで、「TUNAGチャット」へのSSOログインも可能となりました。

最後に

僕は今回、初めて地域Ruby会議に参加しました。そこで感じたのは、自分が使っている道具の構造を知ることの重要性 です。

現実として、アプリケーション側のエンジニアであれば、道具の使い方さえ分かっていれば、内部構造を知らなくても開発は可能です。高水準言語の強みはまさにここにあります。たとえば、多くの開発者は機械語やアセンブリの仕組みを知らなくてもコードを書けますし、私自身も知りません。

コミッターの方々がRubyの内部をブラックボックス化してくれているからこそ、私たちは便利に開発できているわけです。しかしその一方で、構造を理解していないことで見落としたり、最適な使い方ができない場合もあります。

Rubyの内部やメソッドの実装を知っていれば、パフォーマンスチューニングやデバッグでより効率的で安全な判断が可能になります。つまり、「道具の使い方」と「構造の理解」は表裏一体で、両方あって初めて深い応用力が得られるのではないかと感じました。

今回の「ながらRuby会議01」における学びは、普段はブラックボックスとして使っている部分にも興味を持ち、仕組みを知ることで、開発者としての視野や判断力が広がるということです。これからは、自分のコードだけでなく、その下で動く仕組みや背景にも目を向けていきたいと思います。

株式会社スタメンでは、一緒に働く仲間を募集しています!詳しくはこちらをご覧ください🙌

herp.careers