Developer Engagementブロックの@ikkouです。2025年4月16日から18日の3日間にわたり愛媛県は松山市の愛媛県県民文化会館で「RubyKaigi 2025」が開催されました。ZOZOは例年通りプラチナスポンサーとして協賛し、スポンサーブースを出展しました。
本記事では、前半はWEARのバックエンドエンジニアが気になったセッションを紹介します。後半では、ZOZOの協賛ブースの様子と各社のブースにおけるコーディネートを写真中心に報告します。
- ZOZOとWEARとRubyKaigi
- WEARのバックエンドエンジニアが気になったセッション
- ZOZOブースの紹介
- 協賛企業ブースのコーディネートまとめ
- After RubyKaigi 2025〜ZOZO、ファインディ、ピクシブ〜を開催します!
- おわりに
ZOZOとWEARとRubyKaigi
例年、ZOZOがRubyKaigiに協賛していることに疑問を持たれる方もいらっしゃるかもしれませんが、私たちが運営するファッションコーディネートアプリ「WEAR by ZOZO」のバックエンドはRuby on Railsで開発されています。2013年にVBScriptで構築されたシステムでしたが、2020年頃からコードフリーズし、Rubyへのリプレイスを開始しました。現在もリプレイスを進めながら、新規の機能もRubyで開発しています。
ZOZOとRubyKaigiの関係は、ZOZOの前身であるVASILY時代のRubyKaigi 2017に遡ります。コロナ禍を経て再開したRubyKaigi 2022からはWEARのバックエンド開発を担うチームが中心となって協賛とスポンサーブースの出展を続けています。
- RubyKaigi2017参加レポート(全日分)とスライドまとめ
- RubyKaigi2018参加レポート
- RubyKaigi 2019参加レポート〜sonots登壇セッション & エンジニア8名による厳選セッション
- RubyKaigi 2022参加レポート 〜エンジニアによるセッション紹介〜
- RubyKaigi 2023参加レポート 〜エンジニアによるセッション紹介〜
- RubyKaigi 2024 参加レポート
ZOZOとWEARとMatzさん
ZOZOでは“Rubyのパパ”ことMatzさんを技術顧問としてお迎えし、毎月Matz MTGと称したオンラインミーティングを実施しています。このMatz MTGはRubyエンジニアに限らず、誰でも参加可能です。Rubyに特化した話題から、技術全般に関わる興味深い話題まで、幅広く議論できる場として定着しています。RubyKaigi 2025の翌週に開催されたMatz MTGでは、KeebKaigiでRubyKaigiとも縁のある「キーボード」に関する話題として、Matzさんのキーボード論が語られていました。
WEARのバックエンドエンジニアが気になったセッション
今年はWEARチームから4名のバックエンドエンジニアがRubyKaigiに参加しました。本パートでは各エンジニアが特に気になったセッションを個々の視点で紹介します。
Speeding up Class#new
@tsuwatchです。今年もたくさんおもしろいセッションがあって、悩んだのですが、Aaron Patterson(@tenderlove)さんの「Speeding up Class#new」について紹介します。
このセッションは、タイトルの通りClass.new
の速度を向上させることについて解説したものです。その実現方法として着目されたのは、このメソッドがCで実装されている点でした。
Class.new
を実行すると、以下の流れで処理されます。
- オブジェクトをallocateする
- initializeする
- オブジェクトをreturnする
RubyからCへ、そしてまたRubyへと変換していく必要があります。
該当のソースコードはruby/object.cのこちらです。
VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass) { VALUE obj; obj = rb_class_alloc(klass); rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS); return obj; }
なぜ言語の境界をまたぐと遅くなるのか。これはCalling Convention、すなわち呼出規約の違いによるものです。
RubyとCでは、引数の受け渡し方法などが異なります。Rubyではキーワード引数を使用できますが、Cではサポートされていません。例えばハッシュ化するなど、さまざまな変換が必要です。
そのため、Cの処理だけを見れば速いかもしれませんが、言語の境界をまたぐオーバーヘッドにより、全体で見ると速度が遅くなっている可能性があります。したがって、多少遅くともCではなくRubyで実現した方が良いと考えられます。該当の実装はruby/ruby#9289で示されています。
ベンチマークとしてallocations per secondが計測されていました。1つの位置引数では1.8x、キーワード引数が3個で3.2x、10個で6.2xという結果でした。
これにはデメリットもあり、メモリが多少増加することや、エラー時のスタックトレースでClass#new
がなくなってしまうケースもありました。しかし、これらは許容範囲内であると結論づけられていました。
このセッションの内容自体とてもおもしろいものでした。普段からRubyの内部を深く知りたいと思いつつも、Cを読むことに対するハードルを感じていましたが、どういった考え方で読んでいけば良いのかを学ぶことができました。さらにRubyへの興味や好奇心を強く持てるようになったセッションでした。
Automatically generating types by running tests
小山です。私からはTakumi Shotoku(@sinsoku_listy)さんの「Automatically generating types by running tests」を紹介します。
このセッションは、テストの実行を通じて自動的に、rbs-inline用にRBSコメントで型情報を生成してくれるgem「rbs-trace」について解説した発表でした。
rbs-traceは、Rubyのテストを実行しながら、実行されたコードの引数と戻り値の型情報をトレースすることで型情報を収集し、RBS形式で出力します。既存のコード行数が多いアプリケーションに対して、すべてのメソッドに手動でRBSを記述するのは困難であるため、テスト実行時に型宣言できるようにすることを目標に取り組まれているとのことです。
トレースには、Rubyの標準ライブラリであるTracePointを使用しています。TracePointは、Rubyの実行中に特定のイベント(メソッド呼び出しやクラス定義など)をトレースするためのAPIです。
rbs-traceの用法は非常にシンプルです。以下はセッション中で紹介されたサンプルコードです。
trace = RBS::Trace.new # Enable tracing to call methods trace.enable # Call methods user = User.new("Yukihiro", "Matsumoto") user.say_hello # Disable tracing trace.disable # Save RBS type declarations as comments trace.save_comments
このコードを実行すると、user.say_hello
メソッドの引数と戻り値の型情報が収集され、RubyファイルにRBSコメントが挿入されます。
class User # @rbs (String, String) -> void def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end # @rbs () -> String def full_name "#{@first_name} #{@last_name}" end # @rbs () -> void def say_hello puts "hi, #{full_name}." end end
RSpecやMinitestなどのテストフレームワークと組み合わせて使用でき、テストを実行することで、型情報を自動的に生成できます。
テストと型宣言の一致を前提とするため、テストがないメソッドや、テストが不十分なメソッドに対しては型情報が生成されません。また、テストに不備がある場合、型情報も誤って生成される点に注意が必要です。
以下の2つのRailsアプリケーションに対してrbs-traceを実行した結果も紹介されました。
パフォーマンスについても触れられており、ローカルマシン(2021年製のMacBook Pro M1 Max 64GB)でテストを実行した場合、rbs-trace導入前後での実行時間に以下の差異が見られました。
Rails app | rbs-trace導入前 | rbs-trace導入後 | 差分 | 比率 |
---|---|---|---|---|
Redmine | 2m14s | 12m7s | 9m53s | 5.43倍 |
Mastodon | 45s | 2m54s | 2m9s | 3.87倍 |
Timee、movのプロダクトのアプリケーションコードに対してもrbs-trace導入前後にCIでテストを実行した結果、パフォーマンスの差異は以下の通りでした。
Rails app | jobs | rbs-trace導入前 | rbs-trace導入後 | 差分 | 比率 |
---|---|---|---|---|---|
Timee | 35 | 7m16s | 10m40s | 3m24s | 1.47倍 |
mov | 20 | 15m52s | 22m16s | 6m24s | 1.40倍 |
※TimeeではRSpecのActionsにsplit-testを使用。
※movではRSpecのActionsにsplit-tests-by-timingsを使用。
テストの実行時間は増加しますが、rbs-traceの実行は一度のみで済むため、パフォーマンスへの影響は許容範囲内であると述べられていました。
セッションの中盤では以下の課題に対して、rbs-traceで行った改善が紹介されました。具体的な改善点の詳細については割愛しますが、詳細にご興味のある方はセッション資料を参照してください。
- クラスメソッドでNoMethodErrorが発生する
- クラス名がActiveRecord::Relationになる
- void型をサポートしていない
- 並列テストでのトレースができない
将来の展望としては以下の機能を考えているとのことでした。
- より多くの型をサポートする
- ブロック引数、ジェネリクス型、インタフェース型など
- テストが実行される度にRBSコメントを更新する
- gem_rbs_collectionにないgemのRBSファイルを保存する
rbs-traceは既存のアプリケーションに対してテスト駆動で型宣言を行える、画期的で実用的な素晴らしいgemです。WEARもRBSの導入を計画しているので、ぜひrbs-traceを試してみたいです。
Making TCPSocket.new "Happy"!
chikaです。私からはMisaki Shioi(@coe401_)さんの「Making TCPSocket.new "Happy"!」を紹介します。
このセッションでは、Rubyのソケット拡張ライブラリにあるTCPSocket.new
に、Happy Eyeballs Version 2(RFC 8305)(以下HEv2)のアルゴリズムを導入する取り組みが解説されました。
背景として、Rubyのソケット拡張ライブラリにはTCPSocket.new
の他にSocket.tcp
という2系統のTCPクライアント生成APIがあります。
去年開催されたRubyKaigi 2024では「Socket.tcp
にHappy Eyeballs Version 2 (HEv2)を導入する」という取り組みが発表されました。今回はその続編として、C実装であるTCPSocket.new
への移植がテーマでした。
私はこのHEv2というアルゴリズムがあることさえ知らなかったので、HEv2がどういったアルゴリズムか簡単にまとめます。
Happy Eyeballs Version 2(RFC 8305)について
IPv6とIPv4の両方が利用可能な環境において、通信する際にIPv6とIPv4への接続を効率的に試行し、より早く確立できた方を利用するHappy Eyeballsという仕組みがあります。
Happy Eyeballs Version 1(以下、HEv1)では、まずIPv6の接続を試し、約250 ms待機してその時間内に接続が確立できなければIPv4への接続を開始する「簡易フォールバック」という仕組みになっています。
これはシンプルな仕様ですが、課題として「IPv6が接続できない場合に約0.25秒の遅延が発生する」という問題がありました。
これらの問題を解決するためにHEv2が策定されました。HEv2では「先頭のIPv6へ接続後、50 ms待機し、接続が確立できなければIPv4への接続も並列で試す」という仕様に変更され、上記の問題が解消されました。
変更点はこれだけではなく、具体的なHEv1とHEv2の違いは以下の通りとなっています。
項目 | HEv1 (RFC 6555) | HEv2 (RFC 8305) |
---|---|---|
アドレス並び替え | IPv6群→IPv4群の順そのまま | IPv6とIPv4を交互にインターリーブし、片方が連続して詰まるのを防ぐ |
IPv4着手までの待機 | 固定250 ms | 最大50 msだけIPv6を待ち、即座にIPv4も走らせる |
再試行間隔 | 既定なし | 250 ms ごとに次のアドレスを投入(最小100 ms / 最大2 sで調整可) |
同時接続数 | 先頭+タイマーごとに1本追加 | 最大5件まで一気にIPv6を走らせ、以降250 ms間隔で追加 |
失敗時のフォールバック | IPv6が壊れると250 ms以上の遅延が発生しうる | 多くのケースで遅延50 ms程度でIPv4に切替 |
IPv6優先の維持 | IPv4先行になる可能性がある | IPv6の優先と迅速なフォールバックの両立 |
セッションの話に戻ります。既存のRubyにおけるソケット拡張ライブラリでもこの問題が起きており、Ruby実装のSocket.tcp
とC実装のTCPSocket.new
は、従来IPv6→IPv4の順序で逐次名前解決・接続し、IPv6が失敗するとIPv4へのフォールバック遅延していました。
去年のセッションでは、Socket.tcp
にてHEv2アルゴリズムを実装するにあたり、それぞれの状態(start / v4w / v6c / v4c / v46c / v46w / success / failure / timeout)を定義し、それをloopと(巨大な)caseで分岐させるという実装を紹介していました。
「ではこの実装を参考にTCPSocket.new
にも導入しよう!」となったところ、この実装には「状態遷移が複雑で、例えばIPv6/IPv4両方の名前解決が両方とも成功した際などに無駄な処理や漏れが発生する場合がある」という問題があり、去年発表したSocket.tcp
の設計から作り直すことになったのが今回のセッションのメインとなっていました。
改良版のSocket.tcp
では「状態遷移そのものを捨て、1ループ中でできる処理をすべてif文で判定・実行する」ような設計に方針転換してSocket.tcp
を作り直し、TCPSocket.new
へと移植していく、というような形で話されていました。
具体的にはどのように修正したか、どのような問題があったかなどは、私にはかなり難しい内容だったため、説明できる自信がありません。詳細にご興味のある方は、後日公開されるセッション動画を参照してください。問題発覚後の怒涛の修正や作り直し、Ruby 3.4.0のリリース締め切りに間に合うかのヒヤヒヤ感、修正マージ後にRubyのCIがコケまくって真っ赤に炎上した話などがあり、まるでドキュメンタリー映画を見ているようで、非常に臨場感のある興味深い内容でした。
紆余曲折あったそうですが、最終的に無事マージされ、Ruby 3.4.0にHappy Eyeballs v2が追加されたとのことでした!
HEv2適用後のパフォーマンスは以下の通りです。
- ruby-lang.orgに接続する際、HEv2無効の場合0.129 s、有効の場合0.145 sと、僅かなオーバーヘッド
- IPv6壊滅環境:15 s → 0.114 sと大幅短縮し、132.3倍の高速化
ベンチマーク環境では132.3倍の高速化が見られていました!
この発表は非常に印象に残っています。自身の全く知らなかった「新しいネットワーク接続アルゴリズム」を導入するという、それを趣味でキャッチアップしている人が自らRubyに組み込む活動を行い、それによって普段使用しているRubyの通信速度が速くなり、恩恵を受けているという事実に感銘を受けました。
最終的にRubyコミッターになったともおっしゃっていて、「Rubyコミッターはどのような人がどういった経緯でなっているのか」という自分の中で未知だったところが少し明確になるセッションでもありました!
On-the-fly Suggestions of Rewriting Method Deprecations
小島(@KojimaNaoyuki)です。私からはMasato Ohba(@ohbarye)さんの「On-the-fly Suggestions of Rewriting Method Deprecations」を紹介します。
このセッションでは、ライブラリのメソッドが非推奨になったとき、それを利用しているコードを修正する作業を効率化しようという試みが話されていました。
ライブラリの開発者が古いメソッドを削除したいと考えた時、現在はその古いメソッドを非推奨として警告を出すなどをしてユーザーに新しいメソッドへの修正を促し、ユーザーは手動で修正する必要があります。
ユーザーが手動で修正を実施するのは、時間がかかることや新たなバグを生むこと、そして本来すべき開発とは違うところに意識を割かなければならないことが課題とセッションでは言われていました。そこでohbaryeさんは、使用されている非推奨のメソッドを自動で検出し、修正を提案する「deprewriter-ruby」を開発したそうです。
私自身もGemのアップデートを実施する際には、サービスで利用されているメソッドが非推奨や削除されていないかを確認することに多くの時間を割いていたため、非常に魅力的なツールであると感じました。そして、ライブラリ開発者にとっても利用者により明確に非推奨メソッドの修正方法を提示できるため、メリットがあると感じました。
deprewriter-rubyを利用するためには、ライブラリの開発者が非推奨のメソッドとその代わりになるメソッドをdeprewriter-rubyを用いてライブラリ側に定義します。そしてライブラリの利用者には3つのモードが提供されており、それらを使用して非推奨メソッドをライブラリ開発者が定義した代わりのメソッドへ修正できます。
3つのモードは以下の特性を持ちます。
- Log Mode
- 警告と一緒に変更の提案もログに表示する
- Diff Mode
- 非推奨箇所ごとに差分ファイルを作成する
- Rewrite Mode
- 自動で非推奨メソッドを修正して書き換える
セッションでは実際にデモでこれらの動作が紹介されており、ライブラリ開発者側の定義方法も簡潔に記述でき、利用者側も使いやすいと感じました。
セッション中ではdeprewriter-rubyの課題もお話しされており、コード修正のパターンで対応できていないパターンが存在することや、このツールがRubyのエコシステムに受け入れられるかどうかなどが挙げられていました。
特に、Rubyのエコシステムに受け入れられるかどうかについては、deprewriter-rubyがサードパーティのgemで言語に組み込まれた機能ではないこともあり、全てのライブラリ開発者に強制することは現実的でないと言われていました。そのため、現状ではライブラリ利用者自身が変換の定義を記述しdeprewriter-rubyを使用することになります。
deprewriter-rubyを最大限に活用するためには、ライブラリ開発者が積極的に非推奨メソッドの修正(代わりとなるメソッド)定義することが重要であると感じました。
deprewriter-rubyはライブラリ開発者と利用者の双方にメリットをもたらす素晴らしいツールです。本ツールの普及により、ライブラリのバージョンアップ作業が円滑になることが期待されます。
ZOZOブースの紹介
ZOZOのスポンサーブースでは、WEARのリニューアル後にiOSDC Japan 2024やDroidKaigi 2024でも実施した「ファッションジャンル診断」をメインコンテンツとして展示しました。
診断結果に応じてお渡ししていた全144種類のステッカーはRubyKaigi 2025でも好評でした。もともとジャンルによって出現頻度が異なる傾向にありますが、季節の違いか、あるいは技術領域の違いか、他ではそう多くなかったジャンルの出る割合が多いように感じられたのは印象的でした。
この「ファッションジャンル診断」はブース出展専用コンテンツではなく、WEARアプリで実際に試せる機能のひとつです。ブースでアプリをインストールして診断された方だけでなく、既に診断済みの方、あるいはご友人や同僚を伴って再訪される方もいらっしゃり、多くの方々にご興味を持っていただけたことを嬉しく思います。
その他、ZOZOTOWNのボールペンやLINEスタンプ「エンジニア編」をモチーフにしたステッカーなどを無償で配布していました。ZOZOTOWN公式キャラクター「箱猫マックス」のステッカーが技術カンファレンスのブースに並んだのは初めてでした。
改めてZOZOブースにお立ち寄りいただいた皆さん、ありがとうございました!
RubyKaigi公式イベントのスタンプラリー
RubyKaigiでは例年、公式イベントとしてスポンサーブースを巡るスタンプラリーが開催されています。このスタンプラリーは参加者とスポンサーブースのZOZOスタッフが会話する良いきっかけにもなっています。昨年の全20ブースに対して今年は全46ブースと昨対比2倍以上のブースが出展していたので、会期中にコンプリートできた方は多くなかったかもしれません。参加した方はBooth Completeまでたどり着きましたか?
協賛企業ブースのコーディネートまとめ
あっすーです。iOSDC Japan 2024やDroidKaigi 2024と同様に、RubyKaigi 2025の協賛企業ブースを巡り、特に初めて拝見したコーディネートを中心に各社の様子を撮影しました。
協賛ブースでは出展内容や装飾に目が行きがちですが、各社がコーディネートにおいても工夫を凝らしていることが分かりますね! お忙しい中ご協力いただいたブースの皆様、本当にありがとうございました!
After RubyKaigi 2025〜ZOZO、ファインディ、ピクシブ〜を開催します!
5月13日(火)にRubyKaigi 2025スポンサー企業の株式会社ZOZO、ファインディ株式会社、ピクシブ株式会社でRubyKaigi 2025のアフターイベント「After RubyKaigi 2025〜ZOZO、ファインディ、ピクシブ〜」を開催します。
RubyKaigi 2025に参加した方も、参加できなかった方も、ぜひお気軽にご参加ください!
おわりに
ZOZOは毎年RubyKaigiに協賛し、ブースを出展しており、今年も多くの方々との交流を通じて有意義な時間を過ごすことができました。実行委員会の皆様、そして温かく迎えてくださった松山市の皆様に感謝申し上げます。来年も再び素晴らしい時間を共有できることを楽しみにしております!
ZOZOでは、来年のRubyKaigi 2026を一緒に盛り上げるエンジニアを募集しています。ご興味のある方は以下のリンクからご応募ください。
また、会期中は混雑のため、十分にお話しできなかった方もいらっしゃるかもしれません。もし、より詳しく話を聞きたいという方がいらっしゃいましたら、カジュアル面談も受け付けています。
それではまた来年のRubyKaigiでお会いしましょう。函館の地でも素晴らしい出会いがあることを今から楽しみにしています。現場からは以上です!