torutkのブログ

ソフトウェア・エンジニアのブログ

OobGCとGC停止はメモリをフンダンに用意する

id:torutk:20121103の続きです。RubyのWeb(Rack)サーバーUnicornの応答性改善策として紹介されていたOobGCとGC.disableを試してみました。

設定ファイルの変更

次の2つの設定ファイルを修正しました。

config.ru
--- /var/lib/redmine-2.1.2/config.ru.1	2012-09-30 19:42:00.000000000 +0900
+++ /var/lib/redmine-2.1.2/config.ru	2012-11-04 13:34:23.530340955 +0900
@@ -1,4 +1,8 @@
 # This file is used by Rack-based servers to start the application.
 
 require ::File.expand_path('../config/environment',  __FILE__)
+require 'unicorn/oob_gc'
+
+use Unicorn::OobGC, 5
+
 run RedmineApp::Application
unicorn.rb
--- /var/lib/redmine-2.1.2/config/unicorn.rb.1	2012-10-24 04:01:10.737323459 +0900
+++ /var/lib/redmine-2.1.2/config/unicorn.rb	2012-11-04 13:35:40.382851408 +0900
@@ -36,6 +36,7 @@
       Process::GID.change_privilege(target_gid)
       Process::UID.change_privilege(target_uid)
     end
+    GC.disable  # GC停止(5リクエスト毎にGC実行する設定)
   rescue
     if RAILS_ENV = "development"
       STDERR.puts "could not change user, oh well"

メモリ計測

最初、512MBのメモリを割り当てした仮想マシン(KVM)上のCentOS 6で実験していたため、メモリが枯渇しスラッシングが発生、著しく応答性が劣化してしまいました。

そこで、2GBのメモリ割り当てに増強し、Redmineへのアクセス前、アクセス後(1回目、2回目、・・・)のメモリ使用量をtopコマンドで調査してみました。

なお、Unicornはワーカープロセスを2つ起動する設定にしています。

起動直後のtop
Mem:   1922880k total,   276152k used,  1646728k free,    14800k buffers
Swap:  2064376k total,        0k used,  2064376k free,    74900k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1477 root      20   0  414m  85m 6064 S  0.0  4.6   0:07.97 ruby
 1486 redmine   20   0  415m  83m 2032 S  0.0  4.4   0:00.00 ruby
 1489 redmine   20   0  415m  83m 2028 S  0.0  4.4   0:00.00 ruby

unicornワーカープロセス(PIDが1486, 1489)のメモリ常駐量(RES)は80MB強です。

1回目のRedmineアクセス直後
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1489 redmine   20   0  931m 597m 2940 S  0.0 31.8   0:04.53 ruby
 1477 root      20   0  414m  85m 6064 S  0.0  4.6   0:07.97 ruby
 1486 redmine   20   0  417m  84m 2312 S  0.0  4.5   0:00.01 ruby

unicornワーカープロセスの1つ(PID:1489)が一気に600MB近いメモリ常駐量となっています。

2回目のRedmineアクセス直後
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1486 redmine   20   0  934m 601m 3044 S  0.0 32.0   0:04.89 ruby
 1489 redmine   20   0  931m 597m 2940 S  0.0 31.8   0:04.53 ruby
 1477 root      20   0  414m  85m 6064 S  0.0  4.6   0:07.97 ruby

unicornワーカープロセスのもう1つ(PID:1486)が一気に600MBのメモリ常駐量になりました。

3回目以降のunicornワーカープロセスのメモリ常駐量の推移
アクセス回数 PID:1486 PID:1489
3 601m 610m
4 602m 616m
5 602m 625m
6 615m 625m
: : :
i 630m 637m
: : :
k 630m 637m

ということで、ほぼ一定量となっていました。

必要なメモリ

1つのワーカープロセスが使用するメモリが物理メモリ常駐量で10倍近く必要となるので、GC停止&OobGCによる高速化はふんだんにメモリが利用可能な環境が必要です。