From: matz@... (Yukihiro Matsumoto) Date: 2002-10-02T13:53:59+09:00 Subject: [ruby-dev:18428] Re: shrink memory --Multipart_Wed_Oct__2_13:53:58_2002-1 Content-Type: text/plain; charset=ISO-2022-JP まつもと ゆきひろです In message "[ruby-dev:18427] shrink memory" on 02/10/02, nagai@ai.kyutech.ac.jp writes: |一つには TkcItem#delete において,管理用のハッシュからの情報削除の際, |nil を代入するようにしていたという bug が原因でした. | |# これは Hash#delete を使わないといけないですよね. |# 手が空いている方がありましたら,修正して commit していただけると |# 助かります. 了解です。あやしいところを一括で修正しました。 まず1.7.3でコミットしますので、まずいところがあればどなたか 指摘してください。修正を添付しておきます。 |ですが,これを修正しても,Ruby は多量のメモリを占有したままです. |ご存知の方はご存じの通りの体調ですので, |きちんとした問題追跡やデバッグは行っていないのですが, |結局のところ,ウィジェットパスとオブジェクトとの対応を |管理するハッシュが一時的に肥大化して大量のメモリを要求し, |それが不要 ( 管理ハッシュがほぼ空 ) になっても |Ruby がそのメモリを確保したままになっているということのようです. | |例えば irb などで |------------------------------------- |h = {} |(1..1000000).each{|i| h[i] = i} |(1..1000000).each{|i| h.delete(i)} |h = nil |GC.start |------------------------------------- |などとやっても 24MB ほどのメモリを確保したままとなります. | |で,本題なのですが,「当面はこれ以上のメモリは必要としないよ」 |という状況で,余っているメモリを解放する手段を提供するというのは |難しいでしょうか. |もちろん自動でというのは効率上も無理でしょうから, |スクリプトからの手動の要求によってという話です. | |「一時的なりともそれだけを必要とするんだから仕方がない」というのも |事実だとは思いますが,長期間稼働するアプリケーションで |一時的に作業に多量のメモリを必要とするというケースを考えると |メモリ解放手段が用意されていると嬉しいと思うのですが. えーと、おそらくはご存じだと思うのですが、Cには方法でOSにメ モリを返す移植性のある方法がありません。UNIXならbrkを使えば 返せないことはないですが(でもbrkはPOSIXにない)、mallocが管理 している領域には手が出せません。 ということで、これをなんとかする方法は私には思いつかないので す。使われているオブジェクトが全部回収されたヒープをfree()す るくらいならできそうには思うのですが。これもプロセスサイズを 小さくするとは限りませんよね。 まつもと ゆきひろ /:|) --Multipart_Wed_Oct__2_13:53:58_2002-1 Content-Type: text/plain; charset=US-ASCII Content-Disposition: attachment; filename="tk.patch" Content-Transfer-Encoding: 8bit --- tk.rb 2002/09/12 06:27:15 1.34 +++ tk.rb 2002/10/02 04:49:07 @@ -266,3 +266,3 @@ id = $1 if /rb_out (c\d+)/ =~ id - Tk_CMDTBL[id] = nil + Tk_CMDTBL.delete(id) end @@ -284,3 +284,3 @@ def uninstall_win() - Tk_WINDOWS[@path] = nil + Tk_WINDOWS.delete(@path) end @@ -2190,3 +2190,3 @@ SAFE_MODE = #{safe} - %w(#{func_str}).each{|f| METHOD_TBL[f.intern] = nil } + %w(#{func_str}).each{|f| METHOD_TBL.delete(f.intern) } end --- tkafter.rb 2002/06/04 07:03:33 1.5 +++ tkafter.rb 2002/10/02 04:49:07 @@ -66,3 +66,3 @@ if @running == false || @proc_max == 0 || @do_loop == 0 - Tk_CBTBL[@id] = nil ;# for GC + Tk_CBTBL.delete(@id) ;# for GC @running = false @@ -74,3 +74,3 @@ else - Tk_CBTBL[@id] = nil ;# for GC + Tk_CBTBL.delete(@id) ;# for GC @running = false @@ -274,3 +274,3 @@ @after_id = nil - Tk_CBTBL[@id] = nil ;# for GC + Tk_CBTBL.delete(@id) ;# for GC self --- tkcanvas.rb 2002/06/28 14:40:25 1.15 +++ tkcanvas.rb 2002/10/02 04:49:07 @@ -506,3 +506,3 @@ @c.delete @id - CTagID_TBL[@cpath][@id] = nil if CTagID_TBL[@cpath] + CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath] end @@ -690,3 +690,3 @@ @c.delete @id - CItemID_TBL[@path][@id] = nil if CItemID_TBL[@path] + CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] end @@ -765,3 +765,3 @@ def delete - Tk_IMGTBL[@id] = nil if @id + Tk_IMGTBL.delete(@id) if @id tk_call('image', 'delete', @path) --- tkfont.rb 2002/06/04 07:03:33 1.11 +++ tkfont.rb 2002/10/02 04:49:07 @@ -566,3 +566,3 @@ def delete_core_tk4x - Tk_FontNameTBL[@id] = nil + Tk_FontNameTBL.delete(@id) Tk_FontUseTBL.delete_if{|key,value| value == self} @@ -583,3 +583,3 @@ end - Tk_FontNameTBL[@id] = nil + Tk_FontNameTBL.delete(@id) Tk_FontUseTBL.delete_if{|key,value| value == self} @@ -612,3 +612,3 @@ rescue - Tk_FontUseTBL[w] = nil + Tk_FontUseTBL.delete(w) end @@ -646,3 +646,3 @@ rescue - Tk_FontUseTBL[w] = nil + Tk_FontUseTBL.delete(w) end --- tktext.rb 2002/06/28 14:40:25 1.20 +++ tktext.rb 2002/10/02 04:49:07 @@ -687,3 +687,3 @@ tk_call @t.path, 'tag', 'delete', @id - TTagID_TBL[@tpath][@id] = nil if CTagID_TBL[@tpath] + TTagID_TBL[@tpath].delete(@id) if CTagID_TBL[@tpath] end --- tkvirtevent.rb 2001/05/06 15:04:27 1.4 +++ tkvirtevent.rb 2002/10/02 04:49:07 @@ -56,3 +56,3 @@ tk_call('event', 'delete', "<#{@id}>") - TkVirtualEventTBL[@id] = nil + TkVirtualEventTBL.delete(@id) else @@ -60,3 +60,3 @@ *(sequences.collect{|seq| "<#{tk_event_sequence(seq)}>"}) ) - TkVirtualEventTBL[@id] = nil if info == [] + TkVirtualEventTBL.delete(@id) if info == [] end --Multipart_Wed_Oct__2_13:53:58_2002-1--