Project

General

Profile

Actions

Feature #20612

open

Introduce new Epsilon (no-op) GC

Added by eightbitraptor (Matthew Valentine-House) 9 days ago. Updated 6 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:118481]

Description

Summary

[Github PR 11122]

This ticket proposes the introduction of a new GC, modelled on the Epsilon collector introduced in Java 11. This collector is an allocation only collector (ie. GC is a no-op), and is intended solely for testing and experimentation purposes.

Background

This ticket follows up the work in https://bugs.ruby-lang.org/issues/20470 to extract the GC into a GC interface (gc.c) and a seperate implementation (gc_impl.c).

In order to test the extraction against it's stated goals of being able to load a new GC at runtime we need a "second system" GC implementation to continue testing and developing the interface.

Epsilon GC is one of the simplest implementations of a GC that can be used for testing purposes, as it implements the correct interface needed to run Ruby code, but does no collection.

Design

It's modelled on the Epsilon collector introduced in JDK 11: A No-Op collector that implements memory allocation but no memory reclamation. Memory will continue to be allocated until the process exhausts all available memory and is shut down by the OS's OOM killer. This has the lowest possible GC latency, at the expense of memory footprint and throughput.

This collector was built by initially copying the existing GC in it's entirety and stripping out the collection related concerns. For this reason it uses the same heap/page/slot allocation strategy as Ruby's existing GC.

This choice was made for a few reasons:

  • Memory throughput: Traditionally and Epsilon collector would malloc every allocation, this GC uses an already established Ruby allocation implementation to reduce the number of malloc/free calls during allocation, allowing allocation to be faster.
  • Familiarity: Developers of the Ruby GC are already familiar with how allocation works in Ruby, this GC should remain simple to work on.
  • Simplicity: Using the existing allocation strategy allowed us to develop this quickly, and avoid having to deal with alignment issues, or abstraction leakage issues over the API.

Usage

The epsilon collection can be built as a shared library as follows:

Mac:

clang -I../src/include -I. -I../src -I.ext/include/arm64-darwin23 -Wall -undefined dynamic_lookup -g -O0 -dynamiclib -o gc/epsilon.dylib ../src/gc/epsilon.c

Linux:

gcc -O0 -g -I. -I../src/  -I../src/include -I./.ext/include/x86_64-linux/ -Wall -fPIC -shared -lc ../src/gc/epsilon.c -o gc/epsilon.so

Ruby must be built with shared GC support, and the correct library directory set in the configure path.

./configure --with-shared-gc=$(pwd)/gc

Then, the EpsilonGC can be loaded at runtime using the RUBY_GC_LIBRARY environment variable

RUBY_GC_LIBRARY=epsilon.dylib ./ruby test.rb

Evaluation

No benchmarking has been done on this code. This is intended for testing only. We verify that the EpsilonGC builds against the current version of the Ruby GC interface in Github Actions.

Updated by matz (Yukihiro Matsumoto) 7 days ago

We can not read the background of this proposal. Why do you want to have this epsilon GC? Just for the example of the pluggable GC?

Matz.

Updated by eightbitraptor (Matthew Valentine-House) 6 days ago ยท Edited

matz (Yukihiro Matsumoto) wrote in #note-1:

We can not read the background of this proposal. Why do you want to have this epsilon GC? Just for the example of the pluggable GC?

Matz.

There are two primary reasons why I would like this to be merged.

  1. This will be used to write tests to help us improve the pluggable GC interface. I would like to build against this Epsilon collector in CI, as well as building with Ruby's default GC so that we can more easily detect integration problems, or leaky abstractions within the GC interface.

  2. https://bugs.ruby-lang.org/issues/20470#note-3 in this comment, @katei (Yuta Saito) expressed an interest in having a NoGC collector similar to Java's Epsilon collector in order to improve the performance of Ruby on Wasm for short lived processes that don't need to collect objects. I believe that this proposal provides a light weight implementation that could help with this.

Actions

Also available in: Atom PDF

Like1
Like0Like0