summaryrefslogtreecommitdiff
path: root/ext/objspace/lib/objspace.rb
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2020-09-10 13:17:53 +0200
committerAaron Patterson <[email protected]>2020-09-15 09:18:13 -0700
commitfbba6bd4e3dff7a61965208fecae908f10c4edbe (patch)
tree5ff5a909649db3023f1b1e33531b10eb016668a4 /ext/objspace/lib/objspace.rb
parenta0d50465dee5fe1bf1dc916f35cb681b0825aced (diff)
Parse ObjectSpace.dump_all / dump arguments in Ruby to avoid allocation noise
[Feature #17045] ObjectSpace.dump_all should allocate as little as possible in the GC heap Up until this commit ObjectSpace.dump_all allocates two Hash because of `rb_scan_args`. It also can allocate a `File` because of `rb_io_get_write_io`. These allocations are problematic because `dump_all` dumps the Ruby heap, so it should try modify as little as possible what it is observing.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3530
Diffstat (limited to 'ext/objspace/lib/objspace.rb')
-rw-r--r--ext/objspace/lib/objspace.rb87
1 files changed, 87 insertions, 0 deletions
diff --git a/ext/objspace/lib/objspace.rb b/ext/objspace/lib/objspace.rb
new file mode 100644
index 0000000000..7cd7507891
--- /dev/null
+++ b/ext/objspace/lib/objspace.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'objspace.so'
+
+module ObjectSpace
+ class << self
+ private :_dump
+ private :_dump_all
+ end
+
+ module_function
+
+ # call-seq:
+ # ObjectSpace.dump(obj[, output: :string]) # => "{ ... }"
+ # ObjectSpace.dump(obj, output: :file) # => #<File:/tmp/rubyobj20131125-88733-1xkfmpv.json>
+ # ObjectSpace.dump(obj, output: :stdout) # => nil
+ #
+ # Dump the contents of a ruby object as JSON.
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump(obj, output: :string)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyobj .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ _dump(obj, out)
+ end
+
+
+ # call-seq:
+ # ObjectSpace.dump_all([output: :file]) # => #<File:/tmp/rubyheap20131125-88469-laoj3v.json>
+ # ObjectSpace.dump_all(output: :stdout) # => nil
+ # ObjectSpace.dump_all(output: :string) # => "{...}\n{...}\n..."
+ # ObjectSpace.dump_all(output:
+ # File.open('heap.json','w')) # => #<File:heap.json>
+ # ObjectSpace.dump_all(output: :string,
+ # since: 42) # => "{...}\n{...}\n..."
+ #
+ # Dump the contents of the ruby heap as JSON.
+ #
+ # _since_ must be a non-negative integer or +nil+.
+ #
+ # If _since_ is a positive integer, only objects of that generation and
+ # newer generations are dumped. The current generation can be accessed using
+ # GC::count.
+ #
+ # Objects that were allocated without object allocation tracing enabled
+ # are ignored. See ::trace_object_allocations for more information and
+ # examples.
+ #
+ # If _since_ is omitted or is +nil+, all objects are dumped.
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump_all(output: :file, full: false, since: nil)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyheap .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ _dump_all(out, full, since)
+ end
+end