仲村です。

>>>In message Fri, 30 Jul 1999 12:02:13 +0900
    "[ruby-ext:00350] Re: Ruby/Gtk + Imlib patch"
    "Dai.K." <MAP2303 / mapletown.net> writes:

> > > メモに書かれている点については問題はないと思いますが、
> > > 「メモリ使用量がどんどん増えていく」に関しては調べてみます。
> > 
> > 増えていくのは、Xサーバのメモリ使用量なんです。
> > 
> > 調査のために、Data_Wrap_Struct()で指定するfree関数にダミーのfree()関数
> > を割り当てて、メモリが増えていくスクリプトをgdbで動かし、ダミーのfree
> > 関数が呼ばれるタイミングを観察したんです。
> > すると、GC.startが入っていないスクリプト([ruby-ext:00332]のパッチに入
> > れたsampe4.rbとか)では、ダミーfree関数が全く呼ばれませんでした。
> > 当然なのかもしれませんが、GC.startを入れたスクリプトでは、GC.startを実
> > 行するたびにダミーfree関数が呼び出されているのが観察できました。
> 
>   うーん、妙ですね。。。放っておけばいつか GC されると思うんですが。

>   ところで、ダミーfree が呼ばれたら、ちゃんとメモリ使用量は減るんですよね?

はい。ダミーfreeの中でホンモノfreeを呼び出してますので。
結果、Xサーバのほうが減っています。topで確認。

> > 上のことから、GCされるトリガがわかれば調査を進められるかな、と思ったん
> > ですけど、GCまわりは(も)良くわかっていないので、断念。
> 
>   GC はむつかしいですよね。
> # あまり難しくないのかもしれないけれど、勉強しないところだから:-p
>   トリガ話じゃないですが、仕組みは [ruby-dev:3527] あたりをどうぞ。

ありがとうございます。
ruby-devはとってないのでWebで[ruby-dev:3527]を見てみると、

|GCの発生するのは
|
|  * 明示的に呼んだ時(GC.start)
|  * heapを使い切った時
|  * mallocの総計がある一定数を越えた時
|  * file descriptorを使い切った時
|
|などです.基本的にメモリ割当の瞬間に起きますが,予測するのは
|不可能なタイミングですね.

と、ありました。これがGC発生のトリガなんですよね。

[ruby-dev:3527]の上の文章を読んで、今回起こっている現象の原因予想と、
予想から思いつく対策を以下に示してみます。当たっているかどうか。。

  get_pixmapではData_Wrap_Struct()をつかっており、Data_Wrap_Struct()は
  Rubyの知らないところで獲得されたメモリ領域をラップするマクロである。
  そのため、Data_Wrap_Struct()でラップされるメモリは、上の「mallocの総
  計がある一定数を越えた時」の総計計算の対象ではない。そのため、なかな
  か自動的にGCが発生する条件がそろわなかった。しかも、扱うデータは画像
  データであり個々のデータが大きいので、増え方が目立つ。

  対策その1:
    + Ruby/Gtkを使うスクリプトで、GC.startを呼び出してもらうようにする。
  対策その2:
    + メモリ獲得をRubyにやってもらう。Data_Make_Struct()?
      get_pixmap では、Rubyに獲得してもらったメモリを使う。
  対策その3:
    + 拡張ライブラリの get_pixmap 側で、明示的にGC.start相当の処理
      (rb_gc()?)を実行するようにする。

対策その1は論外ですねよね。

対策その2は、GdkImlibの場合ダメっぽいです。メモリ割り当てがImlibの中
で行なわれているので。

とすると、対策その3が現実的な解決方法なんですかね。。
だけど、Cの拡張ライブラリ内からGC.start相当処理を呼び出すとして、
get_pixmapが実行されるたびにGC.startを実行してもいいのかしら。
GC.startの実行コストがそれほど大きくなければ大丈夫だと思うんですが。。

-- 
仲村 秀樹
deki / honda-eng.co.jp, deki / pfu.co.jp, deki / yk.rim.or.jp