ruby-changes:45187
From: tenderlove <ko1@a...>
Date: Wed, 4 Jan 2017 07:42:16 +0900 (JST)
Subject: [ruby-changes:45187] tenderlove:r57260 (trunk): Add `full` option to `ObjectSpace.dump_all`
tenderlove 2017-01-04 07:42:10 +0900 (Wed, 04 Jan 2017) New Revision: 57260 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=57260 Log: Add `full` option to `ObjectSpace.dump_all` The `full` option includes all slots (even `T_NONE`) in the JSON output. This is to help with debugging heap fragmentation. Here is an example usage: ```ruby File.open('heap.json', 'w') do |f| ObjectSpace.dump_all(output: f, full: true) end ``` The `heap.json` file contains all slots, including empty slots. [Feature #13001] [ruby-core:78468] Modified files: trunk/ext/objspace/objspace_dump.c trunk/test/objspace/test_objspace.rb Index: ext/objspace/objspace_dump.c =================================================================== --- ext/objspace/objspace_dump.c (revision 57259) +++ ext/objspace/objspace_dump.c (revision 57260) @@ -21,6 +21,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace_dump.c#L21 #include "objspace.h" static VALUE sym_output, sym_stdout, sym_string, sym_file; +static VALUE sym_full; struct dump_config { VALUE type; @@ -31,6 +32,7 @@ struct dump_config { https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace_dump.c#L32 VALUE cur_obj; VALUE cur_obj_klass; size_t cur_obj_references; + int full_heap; }; PRINTF_ARGS(static void dump_append(struct dump_config *, const char *, ...), 2, 3); @@ -219,6 +221,10 @@ dump_object(VALUE obj, struct dump_confi https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace_dump.c#L221 dump_append(dc, ", \"frozen\":true"); switch (BUILTIN_TYPE(obj)) { + case T_NONE: + dump_append(dc, "}\n"); + return; + case T_NODE: dump_append(dc, ", \"node_type\":\"%s\"", ruby_node_name(nd_type(obj))); break; @@ -318,10 +324,11 @@ dump_object(VALUE obj, struct dump_confi https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace_dump.c#L324 static int heap_i(void *vstart, void *vend, size_t stride, void *data) { + struct dump_config *dc = (struct dump_config *)data; VALUE v = (VALUE)vstart; for (; v != (VALUE)vend; v += stride) { - if (RBASIC(v)->flags) - dump_object(v, data); + if (dc->full_heap || RBASIC(v)->flags) + dump_object(v, dc); } return 0; } @@ -347,9 +354,15 @@ dump_output(struct dump_config *dc, VALU https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace_dump.c#L354 { VALUE tmp; - if (RTEST(opts)) + dc->full_heap = 0; + + if (RTEST(opts)) { output = rb_hash_aref(opts, sym_output); + if (Qtrue == rb_hash_lookup2(opts, sym_full, Qfalse)) + dc->full_heap = 1; + } + if (output == sym_stdout) { dc->stream = stdout; dc->string = Qnil; @@ -474,6 +487,7 @@ Init_objspace_dump(VALUE rb_mObjSpace) https://github.com/ruby/ruby/blob/trunk/ext/objspace/objspace_dump.c#L487 sym_stdout = ID2SYM(rb_intern("stdout")); sym_string = ID2SYM(rb_intern("string")); sym_file = ID2SYM(rb_intern("file")); + sym_full = ID2SYM(rb_intern("full")); /* force create static IDs */ rb_obj_gc_flags(rb_mObjSpace, 0, 0); Index: test/objspace/test_objspace.rb =================================================================== --- test/objspace/test_objspace.rb (revision 57259) +++ test/objspace/test_objspace.rb (revision 57260) @@ -275,6 +275,19 @@ class TestObjSpace < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/objspace/test_objspace.rb#L275 assert_match /"value":"foobar\h+"/, dump end + def test_dump_all_full + assert_in_out_err(%w[-robjspace], <<-'end;') do |output, error| + def dump_my_heap_please + ObjectSpace.dump_all(output: :stdout, full: true) + end + + dump_my_heap_please + end; + heap = output.find_all { |l| JSON.parse(l)['type'] == "NONE" } + assert_operator heap.length, :>, 0 + end + end + def test_dump_all entry = /"bytesize":11, "value":"TEST STRING", "encoding":"UTF-8", "file":"-", "line":4, "method":"dump_my_heap_please", "generation":/ -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/