Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a no-op gc #564

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft

Implement a no-op gc #564

wants to merge 5 commits into from

Conversation

fdelache
Copy link

@fdelache fdelache commented Dec 13, 2024

Try to implement a no-op GC for Ruby.

For the epsilon GC, compile with:
clang -I../include -I. -I../ -I.ext/include/arm64-darwin23 -I/opt/rubies/3.4.0-preview2/include/ruby-3.4.0+0/arm64-darwin23 -Wall -undefined dynamic_lookup -g -O0 -dynamiclib -o gc/librubygc.epsilon.dylib ../gc/epsilon.c

Then configure your ruby to use the shared gc (in your build folder):
mkdir gc
../configure cflags="-fno-omit-frame-pointer" --prefix=$(pwd)/target --disable-install-doc optflags=-O0 --with-opt-dir=$(brew --prefix gmp):$(brew --prefix jemalloc):$(brew --prefix llvm) --wi th-shared-gc=$(pwd)/gc

Then run Ruby with the epsilon GC loaded:
RUBY_GC_LIBRARY=epsilon ./ruby -v test.rb

The version should indicate the GC being used:
ruby 3.4.0dev (2024-12-13T15:23:13Z epsilon-gc ca6664a3eb) +PRISM +GC[epsilon] [arm64-darwin24]

fdelache and others added 5 commits December 12, 2024 13:41
This is a new Garbage collector built using the new GC API introduced in
https://bugs.ruby-lang.org/issues/20470

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 GC has the lowest possible GC latency, at the expense of memory
footprint and throughput.

This is primarily useful for experimentation and testing, and provides a
"second system" in order to continue testing the GC API.

This collector uses the same heap/page/slot allocation strategy as
Ruby's existing GC. This was done 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.

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

[Feature #20612]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants