Project

General

Profile

Actions

Feature #20794

closed

Expose information about the currently running GC module

Added by eightbitraptor (Matt V-H) about 1 month ago. Updated 7 days ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:119506]

Description

Summary

[Github PR #11872]

Currently it's not possible for the user to easily find out information about the currently running GC, and whether modular GC has been enabled.

The linked PR provides a method for the user to query whether modular GC's are enabled, and whether one is active, as well as a Ruby method that exposes the currently active GC.

Background

Since Modular GC was introduced it's been possible to build Ruby with several different GC configurations:

  1. Modular GC disabled. Existing GC is linked statically, and active - This is the default case
  2. Modular GC enabled, but not loaded. Existing GC is linked statically and is active.
  3. Modular GC enabled, and a GC implementation is loaded and overrides the static default GC.

Currently there's not an accurate way of determining which of these states the current Ruby process is in.

This makes writing tests that work accurately given different GC configurations complex. It also means that developers and admins running Ruby aren't able to get accurate information about their Ruby processes.

Proposal

This ticket proposes the following changes:

  • Add GC status to RUBY_DESCRIPTION so it's visible in the output of ruby -v
  • Add a method GC.active_gc_name that will return the name of the currently running GC as a String.

Implementation

The linked PR implements these proposals.

No shared GC support

This is the default case. Ruby statically links and uses the existing GC, with no means to override it.

RUBY_DESCRIPTION is obviously unchanged

❯ ruby -v
ruby 3.4.0dev (2024-10-09T14:20:46Z mvh-active-gc-name 3cb4bd4d43) +PRISM [arm64-darwin24]

and GC.active_gc_name returns nil

❯ ./ruby -e "p GC.active_gc_name"
nil

Shared GC support enabled, Not loaded

This is the case when Ruby has been configured with --with-shared-gc=/path/to/gc but no GC has been explicitly loaded using the RUBY_GC_LIBRARY environment

RUBY_DESCRIPTION will contain +MOD_GC to indicate that shared GC support is built in. This is similar to how +PRISM, and +YJIT work.

❯ ruby -v
ruby 3.4.0dev (2024-10-09T14:38:38Z mvh-active-gc-name 3cb4bd4d43) +PRISM +MOD_GC [arm64-darwin24]

and GC.active_gc_name still returns nil. This is because the existing statically linked GC is in use, and has not been overridden.

❯ ./ruby -e "p GC.active_gc_name"
nil

Shared GC support enabled, and modular GC loaded

This is the case when Ruby has been configured with --with-shared-gc=/path/to/gc and an alternative GC library has been explicitly loaded using the RUBY_GC_LIBRARY environment variable

RUBY_DESCRIPTION will contain +MOD_GC to indicate that shared GC support is built in. This is similar to how +PRISM, and +YJIT work. In addition it will also contain a GC name, which is a human readable name that each concrete GC implementation needs to provide as part of its API.

This is seen here as +MOD_GC[mmtk] - because in this case librubygc.dylib reports it's name as being mmtk

❯ RUBY_GC_LIBRARY=librubygc.dylib ./ruby -v
ruby 3.4.0dev (2024-10-09T14:38:38Z mvh-active-gc-name 3cb4bd4d43) +PRISM +MOD_GC[mmtk] [arm64-darwin24]

GC.active_gc_name returns the GC's name, as configured by the GC module (this will be identical to the reported name loaded into RUBY_DESCRIPTION).

❯ RUBY_GC_LIBRARY=librubygc.dylib ./ruby -e "puts GC.active_gc_name"
mmtk

Conclusion

This should cover all states that the GC can now be in.

Users can now query the state from the command line to see whether modular GC's are enabled and if so, what GC is active.

From Ruby we can use GC.active_gc_name in conjunction with the pre-existing option RbConfig::CONFIG['shared_gc_dir'] to find out this same information.

This will now make it easier to run different Ruby processes with different GC builds, as well as make it easier for GC implementors to write tests that behave correctly in all these circumstances.

Updated by mame (Yusuke Endoh) 16 days ago · Edited

Would a dedicated method like active_gc_name be good? I guess there will be variants and configurations like "mmtk-immix". It does not look good to me to add the information into a string, like HTTP user agent. How about adding key-values to GC.config like { implementation: "mmtk", mmtk_policy: "immix" }?

Updated by peterzhu2118 (Peter Zhu) 15 days ago

I agree that parsing a string from GC.active_gc_name might not be good. My concern with GC.config is that these keys are not configurable at runtime, so the corresponding GC.config(implementation: "something else") will not work. Ideally, I think it should be in GC.stat, but, of course, this means that GC.stat will be returning non-integer keys, which will be a compatibility issue.

Updated by eightbitraptor (Matt V-H) 10 days ago

I've updated the proposed PR to reflect feedback from DevMeeting-2024-11-07. That is:

  • GC.active_gc_name has been replaced with GC.config[:implementation].
  • Attempting to set the GC name using GC.config(implementation: "somethingelse") will raise ArgumentError with the message `Attempting to set read-only key "Implementation").
  • RUBY_DESCRIPTION has been shortened to +GC when built with shared GC support, and +GC[gc_name] when a GC module is explicitly loaded (eg. +GC[mmtk]).
Actions #4

Updated by eightbitraptor (Matt V-H) 7 days ago · Edited

  • Status changed from Open to Closed

Applied in changeset git|ee290c94a3dd0327f3407edb02272d37470edc95.


Include the currently active GC in RUBY_DESCRIPTION

This will add +GC to the version string and Ruby description when
Ruby is compiled with shared gc support.

When shared GC support is compiled in and a GC module has been loaded
using RUBY_GC_LIBRARY, the version string will include the name of
the currently active GC as reported by the rb_gc_active_gc_name function
in the form

+GC[gc_name]

[Feature #20794]

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0