<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/ext/objspace/objspace_dump.c, branch v3_2_11</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>Indicate if a shape is too_complex in ObjectSpace#dump</title>
<updated>2022-12-15T21:41:47+00:00</updated>
<author>
<name>Jemma Issroff</name>
<email>jemmaissroff@gmail.com</email>
</author>
<published>2022-12-15T18:42:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e9ba3042e13313944fd2695731d0d7498532b80f'/>
<id>e9ba3042e13313944fd2695731d0d7498532b80f</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Transition complex objects to "too complex" shape</title>
<updated>2022-12-15T18:06:04+00:00</updated>
<author>
<name>Jemma Issroff</name>
<email>jemmaissroff@gmail.com</email>
</author>
<published>2022-12-08T22:16:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c1ab6ddc9a6fa228caa5d26b118b54855051279c'/>
<id>c1ab6ddc9a6fa228caa5d26b118b54855051279c</id>
<content type='text'>
When an object becomes "too complex" (in other words it has too many
variations in the shape tree), we transition it to use a "too complex"
shape and use a hash for storing instance variables.

Without this patch, there were rare cases where shape tree growth could
"explode" and cause performance degradation on what would otherwise have
been cached fast paths.

This patch puts a limit on shape tree growth, and gracefully degrades in
the rare case where there could be a factorial growth in the shape tree.

For example:

```ruby
class NG; end

HUGE_NUMBER.times do
  NG.new.instance_variable_set(:"@unique_ivar_#{_1}", 1)
end
```

We consider objects to be "too complex" when the object's class has more
than SHAPE_MAX_VARIATIONS (currently 8) leaf nodes in the shape tree and
the object introduces a new variation (a new leaf node) associated with
that class.

For example, new variations on instances of the following class would be
considered "too complex" because those instances create more than 8
leaves in the shape tree:

```ruby
class Foo; end
9.times { Foo.new.instance_variable_set(":@uniq_#{_1}", 1) }
```

However, the following class is *not* too complex because it only has
one leaf in the shape tree:

```ruby
class Foo
  def initialize
    @a = @b = @c = @d = @e = @f = @g = @h = @i = nil
  end
end
9.times { Foo.new }
``

This case is rare, so we don't expect this change to impact performance
of most applications, but it needs to be handled.

Co-Authored-By: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When an object becomes "too complex" (in other words it has too many
variations in the shape tree), we transition it to use a "too complex"
shape and use a hash for storing instance variables.

Without this patch, there were rare cases where shape tree growth could
"explode" and cause performance degradation on what would otherwise have
been cached fast paths.

This patch puts a limit on shape tree growth, and gracefully degrades in
the rare case where there could be a factorial growth in the shape tree.

For example:

```ruby
class NG; end

HUGE_NUMBER.times do
  NG.new.instance_variable_set(:"@unique_ivar_#{_1}", 1)
end
```

We consider objects to be "too complex" when the object's class has more
than SHAPE_MAX_VARIATIONS (currently 8) leaf nodes in the shape tree and
the object introduces a new variation (a new leaf node) associated with
that class.

For example, new variations on instances of the following class would be
considered "too complex" because those instances create more than 8
leaves in the shape tree:

```ruby
class Foo; end
9.times { Foo.new.instance_variable_set(":@uniq_#{_1}", 1) }
```

However, the following class is *not* too complex because it only has
one leaf in the shape tree:

```ruby
class Foo
  def initialize
    @a = @b = @c = @d = @e = @f = @g = @h = @i = nil
  end
end
9.times { Foo.new }
``

This case is rare, so we don't expect this change to impact performance
of most applications, but it needs to be handled.

Co-Authored-By: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add variation_count on classes</title>
<updated>2022-12-15T18:06:04+00:00</updated>
<author>
<name>Jemma Issroff</name>
<email>jemmaissroff@gmail.com</email>
</author>
<published>2022-12-08T21:48:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=a3d552aedd190b0f21a4f6479f0ef1d2ce90189b'/>
<id>a3d552aedd190b0f21a4f6479f0ef1d2ce90189b</id>
<content type='text'>
Count how many "variations" each class creates. A "variation" is a a
unique ordering of instance variables on a particular class. This can
also be thought of as a branch in the shape tree.

For example, the following Foo class will have 2 variations:

```ruby
class Foo ; end

Foo.new.instance_variable_set(:@a, 1) # case 1: creates one variation
Foo.new.instance_variable_set(:@b, 1) # case 2: creates another variation

foo = Foo.new
foo.instance_variable_set(:@a, 1) # does not create a new variation
foo.instance_variable_set(:@b, 1) # does not create a new variation (a continuation of the variation in case 1)
```

We will use this number to limit the amount of shapes that a class can
create and fallback to using a hash iv lookup.

Co-Authored-By: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Count how many "variations" each class creates. A "variation" is a a
unique ordering of instance variables on a particular class. This can
also be thought of as a branch in the shape tree.

For example, the following Foo class will have 2 variations:

```ruby
class Foo ; end

Foo.new.instance_variable_set(:@a, 1) # case 1: creates one variation
Foo.new.instance_variable_set(:@b, 1) # case 2: creates another variation

foo = Foo.new
foo.instance_variable_set(:@a, 1) # does not create a new variation
foo.instance_variable_set(:@b, 1) # does not create a new variation (a continuation of the variation in case 1)
```

We will use this number to limit the amount of shapes that a class can
create and fallback to using a hash iv lookup.

Co-Authored-By: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>objspace_dump.c: don't dump class of T_IMEMO</title>
<updated>2022-12-14T14:53:41+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>byroot@ruby-lang.org</email>
</author>
<published>2022-12-14T14:19:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=1df6d0e57828de9606613db940e32aa5b15eff18'/>
<id>1df6d0e57828de9606613db940e32aa5b15eff18</id>
<content type='text'>
They don't actually have a class.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
They don't actually have a class.
</pre>
</div>
</content>
</entry>
<entry>
<title>[DOC] Don't document private methods in objspace</title>
<updated>2022-12-12T14:48:06+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2022-12-12T14:37:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=0b4fda11ec918e8f40059cfd1d2f417bf780d60d'/>
<id>0b4fda11ec918e8f40059cfd1d2f417bf780d60d</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>objspace_dump.c: dump the capacity field for INITIAL_CAPACITY shapes</title>
<updated>2022-12-09T16:06:21+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>byroot@ruby-lang.org</email>
</author>
<published>2022-12-09T14:22:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d7812d1949b6315eff5088c6f74eaf9ef6b34119'/>
<id>d7812d1949b6315eff5088c6f74eaf9ef6b34119</id>
<content type='text'>
We forgot about that one, it's quite useful to see which capacity
we started from.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We forgot about that one, it's quite useful to see which capacity
we started from.
</pre>
</div>
</content>
</entry>
<entry>
<title>ObjectSpace.dump_all: dump shapes as well</title>
<updated>2022-12-08T17:46:16+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>byroot@ruby-lang.org</email>
</author>
<published>2022-12-06T11:56:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=73771e4b192f3db62efb854affdfc95babba1d35'/>
<id>73771e4b192f3db62efb854affdfc95babba1d35</id>
<content type='text'>
I see several arguments in doing so.

First they use a non trivial amount of memory, so for various memory
profiling/mapping tools it is relevant to have visibility of the space
occupied by shapes.

Then, some pathological code can create a tons of shape, so it is
valuable to have a way to have a way to observe shapes without having
to compile Ruby with `SHAPE_DEBUG=1`.

And additionally it's likely much faster to dump then this way than
to use `RubyVM::Shape`.

There are however a few open questions:

- Shapes can't respect the `since:` argument. Not sure what to do when
  it is provided. Would probably make sense to not dump them.
- Maybe it would make more sense to have a separate `ObjectSpace.dump_shapes`?
- Maybe instead `dump_all` should take a `shapes: false` argument?

Additionally, `ObjectSpace.dump_shapes` is added for the use case of
debugging the evolution of the shape tree.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
I see several arguments in doing so.

First they use a non trivial amount of memory, so for various memory
profiling/mapping tools it is relevant to have visibility of the space
occupied by shapes.

Then, some pathological code can create a tons of shape, so it is
valuable to have a way to have a way to observe shapes without having
to compile Ruby with `SHAPE_DEBUG=1`.

And additionally it's likely much faster to dump then this way than
to use `RubyVM::Shape`.

There are however a few open questions:

- Shapes can't respect the `since:` argument. Not sure what to do when
  it is provided. Would probably make sense to not dump them.
- Maybe it would make more sense to have a separate `ObjectSpace.dump_shapes`?
- Maybe instead `dump_all` should take a `shapes: false` argument?

Additionally, `ObjectSpace.dump_shapes` is added for the use case of
debugging the evolution of the shape tree.
</pre>
</div>
</content>
</entry>
<entry>
<title>Add shape_id to heap dump</title>
<updated>2022-12-05T22:33:16+00:00</updated>
<author>
<name>Jemma Issroff</name>
<email>jemmaissroff@gmail.com</email>
</author>
<published>2022-12-05T19:59:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e4aba8f519ca0b63fb3da11d6573443545aaef9b'/>
<id>e4aba8f519ca0b63fb3da11d6573443545aaef9b</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove numiv from RObject</title>
<updated>2022-11-10T15:11:34+00:00</updated>
<author>
<name>Jemma Issroff</name>
<email>jemmaissroff@gmail.com</email>
</author>
<published>2022-11-08T19:09:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c726c48a3dacd9ca1cb0d96fee98890cb74b37d3'/>
<id>c726c48a3dacd9ca1cb0d96fee98890cb74b37d3</id>
<content type='text'>
Since object shapes store the capacity of an object, we no longer
need the numiv field on RObjects. This gives us one extra slot which
we can use to give embedded objects one more instance variable (for a
total of 3 ivs). This commit removes the concept of numiv from RObject.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Since object shapes store the capacity of an object, we no longer
need the numiv field on RObjects. This gives us one extra slot which
we can use to give embedded objects one more instance variable (for a
total of 3 ivs). This commit removes the concept of numiv from RObject.
</pre>
</div>
</content>
</entry>
<entry>
<title>Use shared flags of the type</title>
<updated>2022-11-02T15:03:21+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2022-11-02T15:03:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=4a8cd9e8bca2be1c14310cc13366ec9177a1f74d'/>
<id>4a8cd9e8bca2be1c14310cc13366ec9177a1f74d</id>
<content type='text'>
The ELTS_SHARED flag is generic, so we should prefer to use the flags
specific of the type (STR_SHARED for strings and RARRAY_SHARED_FLAG
for arrays).
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The ELTS_SHARED flag is generic, so we should prefer to use the flags
specific of the type (STR_SHARED for strings and RARRAY_SHARED_FLAG
for arrays).
</pre>
</div>
</content>
</entry>
</feed>
