Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Avatar for alpaca-tc alpaca-tc
September 06, 2025

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

https://regional.rubykaigi.org/nagara01/ の登壇資料です。

---

Ruby3.2以降、refinementsにおけるメソッド定義はパフォーマンスが大幅に劣化しており、実は3.2〜3.5で1万倍弱遅くなっています。

私たちが開発する社内サービスでRubyをアップデートした際に、Railsアプリケーションの起動に数十秒かかるようになってしまったことで、この問題が発覚しました。

この発表では、どうしてパフォーマンス劣化が発生していたのか、そしてどうやって不具合を修正して高速化したのか、MRIの内部実装を元に解説します。

Avatar for alpaca-tc

alpaca-tc

September 06, 2025
Tweet

More Decks by alpaca-tc

Other Decks in Programming

Transcript

  1. ਪଌ͢ΔͳɺܭଌͤΑ # Gemfile gem 'vernier' # config/application.rb # 計測用のmiddlewareを追加 config.middleware.use(Vernier::Middleware)

    # ファイルを更新してRailsのリロード処理を行う $ touch app/controllers/application_controller.rb $ curl http://localhost:3000/?vernier=true 
  2. ࠶ݱίʔυϕϯνϚʔΫ mod = Module.new klass = Class.new Benchmark.ips do |x|

    x.report(RUBY_VERSION) do mod.send(:refine, klass) { def call = nil } end x.compare! end 
  3. ϕϯνϚʔΫ݁Ռ 10^2 10^4 10^5 10^7 3.2 3.3 3.4 3.5 3322714

    i/s 713 i/s 470 i/s 442 i/s  4656x slower 7060x slower 7505x slower
  4. ͱΓ͋͑ͣ3FWFSUύον $ echo '--- a/vm_method.c +++ b/vm_method.c @@ -304 +303,0

    @@ rb_clear_method_cache(VALUE klass_or_module, ID mid) - rb_clear_all_refinement_method_cache(); ' | rbenv install 3.3.9 —patch ଎౓͸վળ💪 
  5. VTFSEVQ User Object Kernel BasicObject ܧঝνΣʔϯ Kernel#dup  DBMMDBDIFͱ͸Կ͔ w

    ϝιουΛݺͿ w ܧঝνΣʔϯ͔Βϝ ιουఆٛΛ୳͢
  6. VTFSEVQ User Object Kernel BasicObject ܧঝνΣʔϯ Kernel#dup Kernel#dup DBMMDBDIF 

    DBMMDBDIFͱ͸Կ͔ w ϝιουΛݺͿ w ܧঝνΣʔϯ͔Βϝ ιουఆٛΛ୳͢ w ୳ࡧ݁ՌΛΩϟογ ϡ
  7. VTFSEVQ User Object Kernel BasicObject Kernel#dup Kernel#dup User#dup DBMMDBDIF ܧঝνΣʔϯ

    w ϝιουΛ௥Ճ w 6TFSEVQΛࢀর͠ ͍ͨ  ແޮԽॲཧͷඞཁੑ
  8. VTFSEVQ User Object Kernel BasicObject Kernel#dup Kernel#dup User#dup DBMMDBDIF ܧঝνΣʔϯ

    ❌  w ϝιουΛ௥Ճ w 6TFSEVQΛࢀর͠ ͍ͨ w ݹ͍DBMMDBDIFΛഁغ ͢Δૢ࡞ ແޮԽॲཧͷඞཁੑ
  9. 0CKFDU4QBDF Kernel#dup Refined#m User#created_at User#email Kernel#tap Enumerable#max Refined#x DBMMDBDIF DBMMDBDIF

    DBMMDBDIF DBMMDBDIF DBMMDBDIF DBMMDBDIF DBMMDBDIF ❌ ❌  3FGJOFNFOUTؔ࿈ͷ DBMMDBDIFΛফ͢
  10. 0CKFDU4QBDF Kernel#dup DBMMDBDIF User#email DBMMDBDIF Enumerable#map DBMMDBDIF Kernel#tap DBMMDBDIF String("…")

    String("…") 1000 2 <#User …> <#Item …> Array<> <#Item …> 3209 User#email DBMMDBDIF Array<> String("…") String("…") String("…") String("…") 1234 <#Item …> <#Item …> <#Item …> ʜ 
  11. SF fi OFDBMMDBDIFઐ༻ RefinedA#dup RefinedA#size RefinedB#a RefinedC#email RefinedD#tap RefinedA#max RefinedD#map

    DBMMDBDIF DBMMDBDIF DBMMDBDIF DBMMDBDIF DBMMDBDIF DBMMDBDIF DBMMDBDIF Kernel#dup String("…") User#created_at 1000 1010 String("…") Refined#map DBMMDBDIF DBMMDBDIF DBMMDBDIF … 500万オブジェクト 最小限 0CKFDU4QBDF  /&8
  12. 

  13. 

  14. 

  15. मਖ਼ޙϕϯνϚʔΫ݁Ռ 10^2 10^4 10^5 10^7 3.3.9 3.3.9-patch 3.5.0 3.5.0-patch 713

    i/s 442 i/s 2764x faster 4003x faster 2855003 i/s 1222135 i/s