ゴミ箱の中のメモ帳

まだ見ぬ息子たちへ綴る手記

Rubyのweakrefが重い

たまたまweakrefのサンプルコードを書いていたら、Rubyのweakrefが非常に重いことに気がついた。

なんで。weakrefってただの弱参照リファレンスじゃないの。参照カウンタを回さない参照じゃないの。

Rubyに詳しくないからわからないけど、ちょっと調べてみた。

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)


まずテストしたのは下のようなコード。

require 'weakref'

p ObjectSpace.count_objects()
ref = WeakRef.new(Object.new)
p ObjectSpace.count_objects()

また単純。

そして、これを実行してみる。

$ ruby weakref.rb
{:TOTAL=>17581, :FREE=>322, :T_OBJECT=>7, :T_CLASS=>559, :T_MODULE=>22, :T_FLOAT=>7, :T_STRING=>6899, :T_REGEXP=>25, :T_ARRAY=>1450, :T_HASH=>20, :T_BIGNUM=>3, :T_FILE=>13, :T_DATA=>547, :T_MATCH=>110, :T_COMPLEX=>1, :T_NODE=>7576, :T_ICLASS=>20}
{:TOTAL=>17581, :FREE=>249, :T_OBJECT=>9, :T_CLASS=>559, :T_MODULE=>22, :T_FLOAT=>7, :T_STRING=>6961, :T_REGEXP=>25, :T_ARRAY=>1455, :T_HASH=>23, :T_BIGNUM=>3, :T_FILE=>13, :T_DATA=>548, :T_MATCH=>110, :T_COMPLEX=>1, :T_NODE=>7576, :T_ICLASS=>20}

$ ruby2.0 weakref.rb
{:TOTAL=>27253, :FREE=>194, :T_OBJECT=>49, :T_CLASS=>558, :T_MODULE=>23, :T_FLOAT=>4, :T_STRING=>9700, :T_REGEXP=>66, :T_ARRAY=>1994, :T_HASH=>70, :T_BIGNUM=>3, :T_FILE=>24, :T_DATA=>885, :T_MATCH=>21, :T_COMPLEX=>1, :T_RATIONAL=>2, :T_NODE=>13636, :T_ICLASS=>23}
{:TOTAL=>27253, :FREE=>118, :T_OBJECT=>51, :T_CLASS=>558, :T_MODULE=>23, :T_FLOAT=>4, :T_STRING=>9765, :T_REGEXP=>66, :T_ARRAY=>1999, :T_HASH=>73, :T_BIGNUM=>3, :T_FILE=>24, :T_DATA=>886, :T_MATCH=>21, :T_COMPLEX=>1, :T_RATIONAL=>2, :T_NODE=>13636, :T_ICLASS=>23}

Ruby1.9とRuby2.0で試してみたけど同様。おもむろにFREEが減ってる。


仕方がないのでweakrefの実装を見ると、weakref.rbでdelegate.rbを継承していて、そしてdelegate.rbがゴニョゴニョしててよくわからなかった。まぁ、Rubyを使わない私からするとわかるはずもないが、なんかRubyで色々してるっぽい。

よってweakrefを実装しているコードがバックグラウンドでリソースを消費するっぽい。


うーん。weakrefは無駄なメモリを使わないために使うことも多いと思うんだけど、これだと小さなオブジェクトだとweakrefを使わないほうがメモリ消費が少ない気もする。

うーーん。weakrefは説明するのも面倒くさいけど、実装するのも面倒くさいのかな。

うーーーん。weakrefの説明書いてたけど書く気無くしたのでこの文章だけ公開しとく。

パーフェクト Ruby on Rails

パーフェクト Ruby on Rails