From: sam.saffron@... Date: 2017-07-27T16:17:35+00:00 Subject: [ruby-core:82199] [Ruby trunk Bug#13772] Memory leak recycling stacks for threads in 2.4.1 Issue #13772 has been updated by sam.saffron (Sam Saffron). OK I have a standalone repro here: https://gist.github.com/SamSaffron/f43996d5989cefbfbf69e9557ef13b23 Also impacts Ruby head ``` i = 0 def parse_param(s) unless block_given? return enum_for(__method__, s) end while s[0] == ';' s = s[1..-1] ends = s.index(';') while ends && ends > 0 \ && (s[0...ends].count('"') - s[0...ends].scan('\"').count) % 2 != 0 ends = s.index(';', ends + 1) end if ends.nil? ends = s.length end f = s[0...ends] yield f.strip s = s[ends..-1] end nil end def parse_line(line) parts = parse_param(';' + line) key = parts.next pdict = {} begin while (p = parts.next) i = p.index('=') if i name = p[0...i].strip.downcase value = p[i+1..-1].strip if value.length >= 2 && value[0] == '"' && value[-1] == '"' value = value[1...-1] value = value.gsub('\\\\', '\\').gsub('\\"', '"') end pdict[name] = value end end rescue StopIteration end [key, pdict] end while i < 10_000 Thread.new { parse_line("Content-Type:application/json; charset=ISO-8859-1") }.join slots = GC.stat[:heap_live_slots] _,rss = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i) puts "slots #{slots} #{i+=1} threads #{Thread.list.count} rss #{rss}" end puts "done #{RUBY_VERSION}" gets ## # Ruby 2.3.3 # slots 20388, rss 40708 # Ruby 2.4.1 # slots 14448, rss 133688 # # Ruby latest # slots 16071 rss 132968 ``` ---------------------------------------- Bug #13772: Memory leak recycling stacks for threads in 2.4.1 https://bugs.ruby-lang.org/issues/13772#change-65965 * Author: sam.saffron (Sam Saffron) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: 2.4.1 * Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN ---------------------------------------- Per: https://github.com/rest-client/rest-client/issues/611 gem install rest-client ``` 100000.times.each_slice(32) do |slice| slice.map { Thread.new { RestClient.get('echo.jsontest.com/key/value/one/two') } }.each(&:join) GC.start(full_mark: true, immediate_sweep: true) slots = GC.stat[:heap_live_slots] puts "slots #{slots} #{i+=1} threads #{Thread.list.count}" end ``` Causes unbound memory growth on 2.4.1, this was not the case in earlier versions of Ruby or Ruby master. When running through heaptrack and massif-visualizer it looks like all unreclaimed allocations come from thread_recycle_stack Ruby heaps do not grow during tests, all the growth is around unmanaged memory. I feel getting this sorted is urgent, we have seen similar leaks at Discourse. -- https://bugs.ruby-lang.org/ Unsubscribe: