From: zdennis Date: 2006-02-28T05:37:16+09:00 Subject: Re: Memory Question H. Yamamoto, I posted my post and your reply to ruby-core. Hopefully this can get clarified or as you suspect, the problem you potentially found can be fixed, Thank you for your reply, Zach H.Yamamoto wrote: > Hello. > > Ruby's GC is conservative, so there is no guarantee object is freed even if > object is not reachable from GC's root. > > But anyway, probably I found the problem on ELTS_SHARED. > > ///////////////////////////////// > > def pause > GC.start > $stdout.puts "measure memory and hit any key..." > $stdout.flush > $stdin.getc > end > > pause > > a = Array.new(10000){ "." * 1000 } # huge memory > > pause > > a.map!{|s| s[-100..-1]} # memory stays large > > pause > > a.map!{|s| s[-3..-1]} # reduces memory > > pause > > > ///////////////////////////////// > > This is because rb_str_substr (string.c) 's > > else if (len > sizeof(struct RString)/2 && > beg + len == RSTRING(str)->len && !FL_TEST(str, STR_ASSOC)) { > str2 = rb_str_new3(rb_str_new4(str)); > RSTRING(str2)->ptr += RSTRING(str2)->len - len; > RSTRING(str2)->len = len; > } > > is executed at > > a.map!{|s| s[-100..-1]} # memory stays large > > rb_str_new3 generates ELS_SHARED RString which holds original RString. > > When original string becomes unreachable, it should be garbage collected. > But ELTS_SHARED substring references it (RString#aux->shared), so not collected > until substring itself becomes unreachable. > > I haven't confirmed this is really cause of your problem, but there is possibility > this hidden huge string eats memory. (maybe same thing happens on Array) > >