From e0d0bc7474e946d8b107e916cb3ae23e2ea0c957 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 7 Feb 2017 16:54:06 -0800 Subject: [PATCH] Timeout ObjectSpace after 3 minutes `ObjectSpace.each_object` loop takes very long time if there're large number of objects. It's not good idea to not show report for long time and keep consuming CPU. This change adds timeout to avoid the problem. --- lib/sigdump.rb | 63 +++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/lib/sigdump.rb b/lib/sigdump.rb index acab0e3..89ce6e7 100644 --- a/lib/sigdump.rb +++ b/lib/sigdump.rb @@ -66,30 +66,45 @@ def self.dump_object_count(io) io.write "%10s: %s\n" % [_fn(v), k] } - string_size = 0 - array_size = 0 - hash_size = 0 - cmap = {} - ObjectSpace.each_object {|o| - c = o.class - cmap[c] = (cmap[c] || 0) + 1 - if c == String - string_size += o.bytesize - elsif c == Array - array_size = o.size - elsif c == Hash - hash_size = o.size - end - } - - io.write " All objects:\n" - cmap.sort_by {|k,v| -v }.each {|k,v| - io.write "%10s: %s\n" % [_fn(v), k] - } - - io.write " String #{_fn(string_size)} bytes\n" - io.write " Array #{_fn(array_size)} elements\n" - io.write " Hash #{_fn(hash_size)} pairs\n" + begin + measure_start = Time.now + + string_size = 0 + array_size = 0 + hash_size = 0 + cmap = {} + i = 0 + ObjectSpace.each_object {|o| + i += 1 + if i % 1000 == 0 + if Time.now - measure_start > 180 + raise "Measurement timed out (too many objects)" + end + end + + c = o.class + cmap[c] = (cmap[c] || 0) + 1 + if c == String + string_size += o.bytesize + elsif c == Array + array_size = o.size + elsif c == Hash + hash_size = o.size + end + } + + io.write " All objects:\n" + cmap.sort_by {|k,v| -v }.each {|k,v| + io.write "%10s: %s\n" % [_fn(v), k] + } + + io.write " String #{_fn(string_size)} bytes\n" + io.write " Array #{_fn(array_size)} elements\n" + io.write " Hash #{_fn(hash_size)} pairs\n" + + rescue => e + io.write " All objects: #{e}\n" + end io.flush end