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

Rubyのextendであったこわい話

MasashiFujita
August 23, 2024
190

 Rubyのextendであったこわい話

MasashiFujita

August 23, 2024
Tweet

Transcript

  1. 自己紹介 名前:藤田 将志 所属:DIGGLE株式会社 自己紹介: • Ruby on Rails や

    React などを使用した、管理会計のためのtoBのSaasを開発し ています。 ◦ 弊社は2023、2024Ruby会議のスポンサーで、とても Rubyにお世話になっています 😊 • 兵庫県神戸市出身で、とても関西が恋しいです
  2. heap-profiler 実行結果を細かく見ると extendあり Total allocated: 172.37 MB (1342040 objects) Total

    retained: 9.11 MB (34481 objects) allocated objects by file ----------------------------------- 6637 activerecord-7.1.3.4/lib/active_record/relation/query_methods.rb 4148 activerecord-7.1.3.4/lib/active_record/relation.rb 2001 activerecord-7.1.3.4/lib/active_record/relation/batches.rb 815 <internal:kernel> 578 activerecord-7.1.3.4/lib/active_record/relation/delegation.rb extendなし Total allocated: 171.48 MB (1334457 objects) Total retained: 9.10 MB (34108 objects) allocated objects by file ----------------------------------- 2988 activerecord-7.1.3.4/lib/active_record/relation/query_methods.rb 1230 activerecord-7.1.3.4/lib/active_record/relation.rb 1701 activerecord-7.1.3.4/lib/active_record/relation/batches.rb なし <internal:kernel> 476 activerecord-7.1.3.4/lib/active_record/relation/delegation.rb
  3. なんとなくわかったこと1 allocated memory by location ----------------------------------- 645.08 kB <internal:kernel>:48 extendありのケースでは、<internal:kernel>:48

    の実行によっ て、オブジェクトが生成されている ruby/kernel.rb ActiveRecord::QueryMethods#where ActiveRecord::Batches#find_each 内では、relation.whereによって、 User::ActiveRecord_Relation オブジェクトのcloneが発生する → clone 生成物ごとに異なる singleton_class が生成される → 多くのオブジェクトが作成される ActiveRecord::SpawnMethods#spawn
  4. なんとなくわかったこと2 extendありのケースでは、 callcache がより多く生成される。 callcache: インラインメソッドキャッシュ のためのオブジェクト allocated objects by

    class ----------------------------------- 11652 <callcache> (IMEMO) ・・・extendあり 4275 <callcache> (IMEMO) ・・・extendなし インラインメソッドキャッシュ : 笹田 耕一『プログラム言語 Ruby におけるメソッド キャッシング手法の検討』 より引用 メソッドディスパッチ命令 send のオペランドにメ ソッ ドキャッシュ用のオペランドを用意し,その領域に レ シーバのクラスとメソッド定義情報を格納する.ディス パッチ時,レシーバのクラスをキャッシュしたクラス と 比較し,等しければヒットとする. rb_callcache
  5. なんとなくわかったこと2 WEB+DB PRESS Vol.122 笹田 耕一「Rubyのウラガワ」 P.143より引用 注16 クラスが異なるとメソッド探索が失敗します。つまり、同 じクラスのオブジェクト

    でも、それぞれが特異クラスを 持っているとクラスが異なると判定され、キャッ シュが効 きません。性能が必要な場面では特異クラスを作らないよ うにする とよいかもしれません。
  6. なんとなくわかったこと2(補足) 【参考】その他、extendによるメモリ使用量への悪影響 • Call Cache for singleton methods can lead

    to "memory leaks" ◦ 引用:Eregon (Benoit Daloze) さんのコメント As a general note, creating a singleton class is not cheap, this should only be used for class objects (which always have one) and for a few rare global objects where it's convenient. Using Object#extend objects often/on the fast path is just "making programs slow and uncached". (訳)一般的な注意点として、シングルトンクラスの作成はコストが高いので、常にシングルトンクラスを持つクラ スオブジェクトや、便宜上必要な少数のグローバルオブジェクトにのみ使用すべきです。 `Object#extend` を頻 繁に使用したり、高速パスで使用したりすることは、単に「プログラムを遅くし、キャッシュを効かなくする」ことに なります。 • PoC: Cache Extended Collection Proxies