[#100284] [Ruby master Bug#17211] Test failures in ruby2.7.2 and ruby3.0~preview1 — utkarsh@...

Issue #17211 has been reported by utkarsh (Utkarsh Gupta).

10 messages 2020/10/02

[#100301] [Ruby master Feature#17215] Backport for arm64 optimizations that exist for power/x86 — jaruga@...

Issue #17215 has been reported by jaruga (Jun Aruga).

10 messages 2020/10/05

[#100329] [Ruby master Bug#17220] Rails Active Job integration test fails with Ruby 3.0.0 since 2038cc6cab6ceeffef3ec3a765c70ae684f829ed — yasuo.honda@...

Issue #17220 has been reported by yahonda (Yasuo Honda).

28 messages 2020/10/07

[#100332] [Ruby master Bug#17221] Relax the Fiber#transfer's limitation — ko1@...

Issue #17221 has been reported by ko1 (Koichi Sasada).

15 messages 2020/10/07

[#100348] [Ruby master Bug#17257] Integer#pow(0, 1) returns 1, which is incorrect — universato@...

Issue #17257 has been reported by universato (Yoshimine Sato).

13 messages 2020/10/09

[#100371] [Ruby master Feature#17260] Promote pattern matching to official feature — kazuki@...

Issue #17260 has been reported by ktsj (Kazuki Tsujimoto).

10 messages 2020/10/11

[#100383] [Ruby master Feature#17261] Software transactional memory (STM) for Threads and Ractors — ko1@...

Issue #17261 has been reported by ko1 (Koichi Sasada).

14 messages 2020/10/12

[#100401] [Ruby master Bug#17263] Fiber context switch degrades with number of fibers, limit on number of fibers — ciconia@...

Issue #17263 has been reported by ciconia (Sharon Rosner).

14 messages 2020/10/15

[#100422] [CommonRuby Feature#17265] Add `Bool` module — marcandre-ruby-core@...

Issue #17265 has been reported by marcandre (Marc-Andre Lafortune).

11 messages 2020/10/19

[#100466] [Ruby master Feature#17273] shareable_constant_value pragma — ko1@...

Issue #17273 has been reported by ko1 (Koichi Sasada).

14 messages 2020/10/21

[#100471] [Ruby master Feature#17277] Make Enumerator#with_index yield row and col indices for Matrix — grzegorz.jakubiak@...

Issue #17277 has been reported by greggzst (Grzegorz Jakubiak).

8 messages 2020/10/21

[#100479] [Ruby master Feature#17278] On-demand sharing of constants for Ractor [email protected]

Issue #17278 has been reported by Dan0042 (Daniel DeLorme).

13 messages 2020/10/21

[#100534] [Ruby master Feature#17284] Shareable Proc — ko1@...

Issue #17284 has been reported by ko1 (Koichi Sasada).

16 messages 2020/10/25

[#100597] [Ruby master Feature#17288] Optimize __send__ call with a literal method name — muraken@...

Issue #17288 has been reported by mrkn (Kenta Murata).

13 messages 2020/10/27

[#100669] [Ruby master Feature#17295] Feature: Create a directory and file with Pathname#touch — get.codetriage@...

Issue #17295 has been reported by schneems (Richard Schneeman).

9 messages 2020/10/30

[#100673] [Ruby master Feature#17298] Ractor's basket communication APIs — ko1@...

Issue #17298 has been reported by ko1 (Koichi Sasada).

15 messages 2020/10/30

[#100675] [Ruby master Misc#17299] DevelopersMeeting20201120Japan — mame@...

Issue #17299 has been reported by mame (Yusuke Endoh).

11 messages 2020/10/31

[ruby-core:100449] [Ruby master Feature#17176] GC.auto_compact / GC.auto_compact=(flag)

From: tenderlove@...
Date: 2020-10-20 19:39:33 UTC
List: ruby-core #100449
Issue #17176 has been updated by tenderlovemaking (Aaron Patterson).


I made another pull request that sets the default to "ON":

  https://github.com/ruby/ruby/pull/3316

It looks like there is one optional ruby spec test that is failing, but all of the other tests pass.  Since the test suites pass with automatic compaction enabled, it makes me pretty confident about the implementation (though I'm sure there are bugs somewhere).

----------------------------------------
Feature #17176: GC.auto_compact / GC.auto_compact=(flag)
https://bugs.ruby-lang.org/issues/17176#change-88068

* Author: tenderlovemaking (Aaron Patterson)
* Status: Open
* Priority: Normal
----------------------------------------
Hi,

I'd like to make compaction automatic eventually.  As a first step, I would like to introduce two functions:

* GC.enable_autocompact
* GC.disable_autocompact

One function enables auto compaction, the other one disables it.  Automatic compaction is *disabled* by default.  When it is enabled it will happen only on every major GC.

I've made a pull request here: https://github.com/ruby/ruby/pull/3547

This patch makes _object movement_ happen at the same time as page sweep.  When one page finishes sweeping, that page is filled.

## Sweep + Move Phase

During sweep, we keep a pointer to the current sweeping page.  This pointer is kept in [`heap->sweeping_page`](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4817).  At the beginning of sweep, this is the *first* element of the heap's linked list.

At the same time, the compaction process points at the *last* page in the heap, and that is stored in `heap->compact_cursor` [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L5023).

Incremental sweeping sweeps one page at a time in the [`gc_page_sweep` function](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4624).  At the end of that function, we call [`gc_fill_swept_page`](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4738-L4742).  `gc_fill_swept_page` fills the page that was just swept and moves the movement cursor towards the sweeping cursor.

When the sweeping cursor and the movement cursor meet, sweeping is paused, and references are updated.  This can happen in 2 ways, the sweeping cursor "runs in to the moving cursor" which is [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4634-L4644).  Or the moving cursor runs in to the sweep cursor which happens [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4425-L4430).

Either way, the sweep step is paused and references are updated.

## Reference Updating

Reference updating hasn't changed, but since reference updating happens before the GC finishes a cycle, it must take in to account garbage objects [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L8971-L8977).

## Read Barrier

During the sweep phase, some objects may touch other objects.  For example, `T_CLASS` [must remove itself from a parent class](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L2769-L2770).

```ruby
class A; end
class B < A; end

const_set(:B, nil)
```

When `B` is freed, it must remove itself from `A`'s subclasses.  But what if `A` moved?  To fix this, I've introduced a read barrier.  The read barrier protects `heap_page_body` using `mprotect`.  If something tries to read from the page, an exception will occur and we can move all objects back to the page (invalidate the movement).

The lock function is [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4321-L4335).
The unlock function is [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4337-L4351).

It uses `sigaction` to catch the exception [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4514-L4530).

## Cross Platform

`mprotect` and `sigaction` are not cross platform, they doesn't work on Windows. On Windows the read barrier uses exception handlers that are built in to Windows.  I implemented them [here](https://github.com/ruby/ruby/blob/8a4d8fa0ea463d44486bf2447ea9830593768fd7/gc.c#L4471-L4503).

The read barrier seems to work on all platforms we're testing.

## Statistics

`GC.stat(:compact_count)` contains the number of times compaction has happened, so we can write things like this:

```ruby
GC.enable_autocompact

cc = GC.stat(:compact_count)
list = []
loop do
  500.times { list << Object.new }
  break if cc < GC.stat(:compact_count)
end

p GC.stat(:compact_count)
```

We can check when the read barrier is triggered with `GC.stat(:read_barrier_faults)`

I've also added `GC.latest_compact_info` so you can see what types of objects moved and how many.  For example:

```
[aaron@tc-lan-adapter ~/g/ruby (autocompact)]$ cat test.rb
list = []
500.times {
  list << Object.new
  Object.new
  Object.new
}

GC.enable_autocompact
count = GC.stat :compact_count
loop do
  list << Object.new
  break if GC.stat(:compact_count) > count
end

p GC.latest_compact_info
[aaron@tc-lan-adapter ~/g/ruby (autocompact)]$ make runruby
./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems ./test.rb
{:considered=>{:T_OBJECT=>408}, :moved=>{:T_OBJECT=>408}}
[aaron@tc-lan-adapter ~/g/ruby (autocompact)]$
```

## Recap

New methods:

* GC.enable_autocompact
* GC.disable_autocompact
* GC.last_compact_info

New statistics in `GC.stat`:

* GC.stat(:read_barrier_faults)

Diff is here: https://github.com/ruby/ruby/pull/3547



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread