From: "H.Yamamoto" Date: 2006-02-27T13:55:51+09:00 Subject: Re: Memory Question 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)