Rubyのプロセスが掴んでいる実メモリを解放する手段はありますか？


Rubyのスクリプトが一度でも巨大なメモリを確保してしまうと、ずっとメモリを保持し続けてしまう現象に悩んでいます。

[code]

    require 'objspace'
    
    array = []
    (1..20).each_with_index do |i|
      array << 'a'*1000000
      puts "memsize: #{ObjectSpace.memsize_of_all / 1024} KB, rss: #{`ps -o rss= #{Process.pid}`.chomp} KB"
    
      if i % 5 == 0
        array = []
        GC.start
        puts "memsize: #{ObjectSpace.memsize_of_all / 1024} KB, rss: #{`ps -o rss= #{Process.pid}`.chomp} KB"
      end
    end
    
[/code]

こんな感じのコードを書くと、実行結果は以下のようになります。

[code]

    memsize: 4125 KB, rss:   8016 KB
    memsize: 5113 KB, rss:   9000 KB
    memsize: 6092 KB, rss:  10000 KB
    memsize: 7071 KB, rss:  11000 KB
    memsize: 8050 KB, rss:  11984 KB
    memsize: 2473 KB, rss:  11988 KB
    memsize: 3452 KB, rss:  11988 KB
    memsize: 4431 KB, rss:  11988 KB
    memsize: 5410 KB, rss:  11988 KB
    memsize: 6389 KB, rss:  11988 KB
    memsize: 7368 KB, rss:  11988 KB
    memsize: 2473 KB, rss:  11988 KB
    memsize: 3452 KB, rss:  11988 KB
    memsize: 4431 KB, rss:  11988 KB
    memsize: 5410 KB, rss:  11988 KB
    memsize: 6389 KB, rss:  11988 KB
    memsize: 7368 KB, rss:  11988 KB
    memsize: 2473 KB, rss:  11988 KB
    memsize: 3452 KB, rss:  11988 KB
    memsize: 4431 KB, rss:  11988 KB
    memsize: 5410 KB, rss:  11988 KB
    memsize: 6389 KB, rss:  11988 KB
    memsize: 7368 KB, rss:  11988 KB
    memsize: 2473 KB, rss:  11988 KB
    
[/code]

時間を伸ばしたり、外からpsコマンドを実行したりしましたが、どうやってもRSSが減りません。  
Rubyオブジェクトに割り当てられたメモリは解放されているのに、せっかく開放したメモリをOSには返却してくれないようです。  
このプロセスに限れば確保したメモリを再利用できるからいいのですが、サーバー上には他のプロセスも動いてるわけでやはり使わなくなったメモリはOSに戻したいです。  
Rubyの仕様上、難しいことでしょうか？




Ruby ではオブジェクトを破棄しても free されにくい実装と記憶しています。(結構前の話なので今は変わっているかも?)
またCレベルの話をすると、free を呼んでもOSにメモリを返さず、次に malloc した際に再割当するような実装も多く存在します。

ということで、一般的にはメモリの解放によっても占有メモリが減らない前提でプログラミングすることになろうかと思います。

どうしてもということであれば、メモリが解放されるようなRubyのバージョン (もし存在すれば)
とmalloc/freeの実装の組み合わせを固定して開発する必要があるでしょう。

