<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/internal/gc.h, 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>Move definition of SIZE_POOL_COUNT back to gc.h</title>
<updated>2022-12-15T21:33:46+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2022-12-15T18:54:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c505448cdbd4cd1a52ed7108095f6738d29b3419'/>
<id>c505448cdbd4cd1a52ed7108095f6738d29b3419</id>
<content type='text'>
SIZE_POOL_COUNT is a GC macro, it should belong in gc.h and not shape.h.
SIZE_POOL_COUNT doesn't depend on shape.h so we can have shape.h depend
on gc.h.

Co-Authored-By: Matt Valentine-House &lt;matt@eightbitraptor.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
SIZE_POOL_COUNT is a GC macro, it should belong in gc.h and not shape.h.
SIZE_POOL_COUNT doesn't depend on shape.h so we can have shape.h depend
on gc.h.

Co-Authored-By: Matt Valentine-House &lt;matt@eightbitraptor.com&gt;
</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>Transition shape when object's capacity changes</title>
<updated>2022-11-10T15:11:34+00:00</updated>
<author>
<name>Jemma Issroff</name>
<email>jemmaissroff@gmail.com</email>
</author>
<published>2022-11-08T20:35:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=5246f4027ec574e77809845e1b1f7822cc2a5cef'/>
<id>5246f4027ec574e77809845e1b1f7822cc2a5cef</id>
<content type='text'>
This commit adds a `capacity` field to shapes, and adds shape
transitions whenever an object's capacity changes. Objects which are
allocated out of a bigger size pool will also make a transition from the
root shape to the shape with the correct capacity for their size pool
when they are allocated.

This commit will allow us to remove numiv from objects completely, and
will also mean we can guarantee that if two objects share shapes, their
IVs are in the same positions (an embedded and extended object cannot
share shapes). This will enable us to implement ivar sets in YJIT using
object shapes.

Co-Authored-By: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This commit adds a `capacity` field to shapes, and adds shape
transitions whenever an object's capacity changes. Objects which are
allocated out of a bigger size pool will also make a transition from the
root shape to the shape with the correct capacity for their size pool
when they are allocated.

This commit will allow us to remove numiv from objects completely, and
will also mean we can guarantee that if two objects share shapes, their
IVs are in the same positions (an embedded and extended object cannot
share shapes). This will enable us to implement ivar sets in YJIT using
object shapes.

Co-Authored-By: Aaron Patterson &lt;tenderlove@ruby-lang.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Increase SIZE_POOL_COUNT to 5</title>
<updated>2022-05-09T12:45:24+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2022-05-04T13:05:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=a41fbc2c95cc2f7ba9071aca091d8262a8f2cf60'/>
<id>a41fbc2c95cc2f7ba9071aca091d8262a8f2cf60</id>
<content type='text'>
Having more size pools will allow us to allocate larger objects
through Variable Width Allocation.

I have attached some benchmark results below.

Discourse:
  On Discourse, we don't see much change in response times. We do see
  a small reduction in RSS.

  Branch RSS: 377.8 MB
  Master RSS: 396.3 MB

railsbench:
  On railsbench, we don't see a big change in RPS or p99 performance.
  We see a small increase in RSS.

  Branch RPS: 815.38
  Master RPS: 811.73

  Branch p99: 1.69 ms
  Master p99: 1.68 ms

  Branch RSS: 90.6 MB
  Master RSS: 89.4 MB

liquid:
  We don't see a significant change in liquid performance.

  Branch parse &amp; render: 29.041 I/s
  Master parse &amp; render: 29.211 I/s
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Having more size pools will allow us to allocate larger objects
through Variable Width Allocation.

I have attached some benchmark results below.

Discourse:
  On Discourse, we don't see much change in response times. We do see
  a small reduction in RSS.

  Branch RSS: 377.8 MB
  Master RSS: 396.3 MB

railsbench:
  On railsbench, we don't see a big change in RPS or p99 performance.
  We see a small increase in RSS.

  Branch RPS: 815.38
  Master RPS: 811.73

  Branch p99: 1.69 ms
  Master p99: 1.68 ms

  Branch RSS: 90.6 MB
  Master RSS: 89.4 MB

liquid:
  We don't see a significant change in liquid performance.

  Branch parse &amp; render: 29.041 I/s
  Master parse &amp; render: 29.211 I/s
</pre>
</div>
</content>
</entry>
<entry>
<title>Decouple incremental marking step from page sizes</title>
<updated>2022-03-30T13:33:17+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2022-03-29T17:57:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=dde164e968e382d50b07ad4559468885cbff33ef'/>
<id>dde164e968e382d50b07ad4559468885cbff33ef</id>
<content type='text'>
Currently, the number of incremental marking steps is calculated based
on the number of pooled pages available. This means that if we make Ruby
heap pages larger, it would run fewer incremental marking steps (which
would mean each incremental marking step takes longer).

This commit changes incremental marking to run after every
INCREMENTAL_MARK_STEP_ALLOCATIONS number of allocations. This means that
the behaviour of incremental marking remains the same regardless of the
Ruby heap page size.

I've benchmarked against discourse benchmarks and did not get a
significant change in response times beyond the margin of error. This is
expected as this new incremental marking algorithm behaves very
similarly to the previous one.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently, the number of incremental marking steps is calculated based
on the number of pooled pages available. This means that if we make Ruby
heap pages larger, it would run fewer incremental marking steps (which
would mean each incremental marking step takes longer).

This commit changes incremental marking to run after every
INCREMENTAL_MARK_STEP_ALLOCATIONS number of allocations. This means that
the behaviour of incremental marking remains the same regardless of the
Ruby heap page size.

I've benchmarked against discourse benchmarks and did not get a
significant change in response times beyond the margin of error. This is
expected as this new incremental marking algorithm behaves very
similarly to the previous one.
</pre>
</div>
</content>
</entry>
<entry>
<title>Change darray size to size_t and add functions that use GC malloc</title>
<updated>2022-02-16T14:50:29+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2022-02-15T14:55:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=71afa8164d40f18306fc2ee5a1ccc74f2926379b'/>
<id>71afa8164d40f18306fc2ee5a1ccc74f2926379b</id>
<content type='text'>
Changes size and capacity of darray to size_t to support more
elements.

Adds functions to darray that use GC allocation functions.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Changes size and capacity of darray to size_t to support more
elements.

Adds functions to darray that use GC allocation functions.
</pre>
</div>
</content>
</entry>
<entry>
<title>Speed up Ractors for Variable Width Allocation</title>
<updated>2021-11-23T15:51:27+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2021-11-19T19:51:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=9aded89f4071a8afb79326701789241f1da12f82'/>
<id>9aded89f4071a8afb79326701789241f1da12f82</id>
<content type='text'>
This commit adds a Ractor cache for every size pool. Previously, all VWA
allocated objects used the slowpath and locked the VM.

On a micro-benchmark that benchmarks String allocation:

VWA turned off:
  29.196591   0.889709  30.086300 (  9.434059)

VWA before this commit:
  29.279486  41.477869  70.757355 ( 12.527379)

VWA after this commit:
  16.782903   0.557117  17.340020 (  4.255603)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This commit adds a Ractor cache for every size pool. Previously, all VWA
allocated objects used the slowpath and locked the VM.

On a micro-benchmark that benchmarks String allocation:

VWA turned off:
  29.196591   0.889709  30.086300 (  9.434059)

VWA before this commit:
  29.279486  41.477869  70.757355 ( 12.527379)

VWA after this commit:
  16.782903   0.557117  17.340020 (  4.255603)
</pre>
</div>
</content>
</entry>
<entry>
<title>gc.h: move rb_objspace_garbage_object_p to internal/gc.h</title>
<updated>2021-11-10T01:08:30+00:00</updated>
<author>
<name>Yusuke Endoh</name>
<email>mame@ruby-lang.org</email>
</author>
<published>2021-11-09T15:57:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e8086e275b9a4896ac57dfeac9b22cbc2741d6d1'/>
<id>e8086e275b9a4896ac57dfeac9b22cbc2741d6d1</id>
<content type='text'>
... to allow class.c to use the function
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
... to allow class.c to use the function
</pre>
</div>
</content>
</entry>
<entry>
<title>[Feature #18239] Implement VWA for strings</title>
<updated>2021-10-25T17:26:23+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2021-08-26T14:06:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=a5b6598192c30187b19b892af3110a46f6a70d76'/>
<id>a5b6598192c30187b19b892af3110a46f6a70d76</id>
<content type='text'>
This commit adds support for embedded strings with variable capacity and
uses Variable Width Allocation to allocate strings.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This commit adds support for embedded strings with variable capacity and
uses Variable Width Allocation to allocate strings.
</pre>
</div>
</content>
</entry>
<entry>
<title>[Feature #18239] Refactor RVARGC alloc functions</title>
<updated>2021-10-25T17:26:23+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2021-08-02T18:22:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=6374be5a8188ff5ed2c70b9f1d76672c87a0eda7'/>
<id>6374be5a8188ff5ed2c70b9f1d76672c87a0eda7</id>
<content type='text'>
The allocation functions no longer assume that one RVALUE needs to be
allocated.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The allocation functions no longer assume that one RVALUE needs to be
allocated.
</pre>
</div>
</content>
</entry>
</feed>
