summaryrefslogtreecommitdiff
path: root/ext/objspace/lib/objspace.rb
blob: 47873f511267962783f760bbd19995a7dffa51ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# frozen_string_literal: true

require 'objspace.so'

module ObjectSpace
  class << self
    private :_dump
    private :_dump_all
    private :_dump_shapes
  end

  module_function

  # Dump the contents of a ruby object as JSON.
  #
  # _output_ can be one of: +:stdout+, +:file+, +:string+, or IO object.
  #
  # * +:file+ means dumping to a tempfile and returning corresponding File object;
  # * +:stdout+ means printing the dump and returning +nil+;
  # * +:string+ means returning a string with the dump;
  # * if an instance of IO object is provided, the output goes there, and the object
  #   is returned.
  #
  # 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

    ret = _dump(obj, out)
    return nil if output == :stdout
    ret
  end


  # Dump the contents of the ruby heap as JSON.
  #
  # _output_ argument is the same as for #dump.
  #
  # _full_ must be a boolean. If true, all heap slots are dumped including the empty ones (+T_NONE+).
  #
  # _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.
  #
  # _shapes_ must be a boolean or a non-negative integer.
  #
  # If _shapes_ is a positive integer, only shapes newer than the provided
  # shape id are dumped. The current shape_id can be accessed using <tt>RubyVM.stat(:next_shape_id)</tt>.
  #
  # If _shapes_ is +false+, no shapes are dumped.
  #
  # To only dump objects allocated past a certain point you can combine _since_ and _shapes_:
  #   ObjectSpace.trace_object_allocations
  #   GC.start
  #   gc_generation = GC.count
  #   shape_generation = RubyVM.stat(:next_shape_id)
  #   call_method_to_instrument
  #   ObjectSpace.dump_all(since: gc_generation, shapes: shape_generation)
  #
  # 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, shapes: true)
    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

    shapes = 0 if shapes == true
    ret = _dump_all(out, full, since, shapes)
    return nil if output == :stdout
    ret
  end

  #  Dump the contents of the ruby shape tree as JSON.
  #
  #  _output_ argument is the same as for #dump.
  #
  #  If _since_ is a positive integer, only shapes newer than the provided
  #  shape id are dumped. The current shape_id can be accessed using <tt>RubyVM.stat(:next_shape_id)</tt>.
  #
  #  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_shapes(output: :file, since: 0)
    out = case output
    when :file, nil
      require 'tempfile'
      Tempfile.create(%w(rubyshapes .json))
    when :stdout
      STDOUT
    when :string
      +''
    when IO
      output
    else
      raise ArgumentError, "wrong output option: #{output.inspect}"
    end

    ret = _dump_shapes(out, since)
    return nil if output == :stdout
    ret
  end
end