From b646fc522337c3c506399e68c0dab034ab98d4fc Mon Sep 17 00:00:00 2001 From: Richard Schneeman Date: Wed, 18 Dec 2019 12:37:46 -0600 Subject: [PATCH] Manually compact GC before fork (#2093) Rub 2.7.0 introduced `GC.compact` which allows manual compaction of Ruby slots. A good time to do this is before forking so that memory fragmentation can be reduced. - https://www.ruby-lang.org/en/news/2019/12/17/ruby-2-7-0-rc1-released/ - https://www.youtube.com/watch?v=1F3gXYhQsAY One issue with memory fragmentation when forking is that while a page in memory might have only one free slot, as that slot is written to after fork, the entire page is written so the benefit of CoW optimizations are greatly reduced. Manually compacting GC reduces the number of pages with empty slots. This PR manually compacts memory right before Puma forks and after other `before_fork` hooks are called. --- .travis.yml | 1 + History.md | 1 + lib/puma/cluster.rb | 1 + 3 files changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 86dbcb2c..a30d460f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,7 @@ matrix: - rvm: ruby-head env: jit=yes - rvm: truffleruby + - rvm: 2.7.0-preview3 allow_failures: - rvm: jruby-9.2.9.0 diff --git a/History.md b/History.md index ddae41bf..8d14b0da 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ * Add pumactl `thread-backtraces` command to print thread backtraces (#2053) * Configuration: `environment` is read from `RAILS_ENV`, if `RACK_ENV` can't be found (#2022) * `Puma.stats` now returns a Hash instead of a JSON string (#2086) + * `GC.compact` is called before fork if available (#2093) * Bugfixes * Your bugfix goes here (#Github Number) diff --git a/lib/puma/cluster.rb b/lib/puma/cluster.rb index f68ad151..97ee976b 100644 --- a/lib/puma/cluster.rb +++ b/lib/puma/cluster.rb @@ -486,6 +486,7 @@ module Puma @master_read, @worker_write = read, @wakeup @launcher.config.run_hooks :before_fork, nil + GC.compact if GC.respond_to?(:compact) spawn_workers