Project

General

Profile

Actions

Feature #20612

open

Introduce new Epsilon (no-op) GC

Added by eightbitraptor (Matt V-H) 5 months ago. Updated 4 months 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) 4 months 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 (Matt V-H) 4 months 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.

Updated by ko1 (Koichi Sasada) 4 months ago

Another question is about naming, "Epsilon" is common term for users?

Updated by peterzhu2118 (Peter Zhu) 4 months ago

"Epsilon" is the term used by the JVM's no-op garbage collector: https://openjdk.org/jeps/318

I don't have a strong opinion on naming, I think either "no-op" or "epsilon" is ok.

Updated by mame (Yusuke Endoh) 4 months ago

eightbitraptor (Matthew Valentine-House) wrote in #note-2:

  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.

I don't think it is good to increase the number of compilation settings unless they could be actually used.
I think your main motivation of the pluggable GC is a MMTk-based GC. If so, please add a CI variant for MMTk.
Unnecessary generalizations are not a good idea.

  1. 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.

Please don't count this use case for now.
I talked with @katei (Yuta Saito). For short lived Wasm processes, a preprocess called "pre-init" is often used, which creates a new Wasm image that has already done the initialization phase. Typically, we need to set normal GC during the initialization phase and set no-op GC in pre-init image. It is uncertain whether the pluggable GC framework actually helps this or not. We need a demonstration experiment.

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0