RubyがもっとCoWフレンドリーになりそう

  • Implement Process.warmup by byroot · Pull Request #7662 · ruby/ruby
  • Feature #18885: End of boot advisory API for RubyVM - Ruby master - Ruby Issue Tracking System
  • Ruby本体にProcess.warmupというメソッドが追加される
  • アプリケーション側でbootが終わったぞ、というときに使う
  • unicornやpumaなどのpreforkするタイプのアプリケーションはforkするので、そのタイミングでいい感じにCoWフレンドリーになるようにしたい
    • 例えば ko1/nakayoshi_fork を使うとforkの時点でGCを4回実行*1して、すべてのオブジェクトを古い世代にすることでCoWフレンドリーにする
      • オブジェクトが何回GCを生き延びたか、というフラグを持っているのでなにもしないとGCのタイミングでオブジェクトが書き換わり、親プロセスと子プロセスで差分ができてしまう
    • nakayoshi_fork自体は単純に4回GCを実行している
    • けど、Rubyの内部に「いまいるオブジェクトを全部古い世代にする」APIがあればそれ使ったほうが効率的ですよね
    • あと「複数のワーカプロセスをforkで生成する」ケースだとforkにフックをかけるやり方だとforkする回数分同じ処理が実行されるので効率が悪い
    • そこでアプリケーションの起動が終わったタイミングでおもむろにProcess.warmupを実行し、そこでもろもろいい感じにCoWフレンドリーにしてやると良い
    • とりあえず上記PRではGC、GC.compact、いまいるオブジェクトを古い世代にするということをProcess.warmupのタイミングでやっている
    • 他にもメソッドや定数のインラインキャッシュをキャッシュに載せておく、とかもっと最適化の余地がある模様
  • Ruby3.3だとpumaやunicornのメモリ消費量が減る、といいう未来がありそう
  • Rubyの最適化、もうあらかた実施済みなのかな、と思ってたけどまだやる余地あるんですね…

*1:3回GCを生き延びたら古い世代になる認識なんだけどなんで4回なんでしょうね…?