Module: GC
Overview
The GC module provides an interface to Ruby's mark-and-sweep garbage collection mechanism.
Some of the underlying methods are also available via the ::ObjectSpace module.
You may obtain information about the operation of the GC through GC::Profiler.
Class Attribute Summary
-
.measure_total_time ⇒ Boolean
rw
Returns the setting for GC total time measurement in the current Ractor; the main Ractor's initial setting is
trueand, with the defaultGC, other Ractors inherit their creator's setting. -
.measure_total_time=(setting) ⇒ setting
rw
Enables or disables GC total time measurement; returns
setting. -
.stress ⇒ setting
rw
Returns the current GC stress-mode setting, which initially is
false. -
.stress=(value) ⇒ value
rw
Enables or disables stress mode.
Class Method Summary
-
.config ⇒ Hash
This method is implementation-specific to CRuby.
-
.count ⇒ Integer
Returns the total number of times garbage collection has occurred:
-
.disable ⇒ Boolean
Disables garbage collection (but .start remains potent): returns whether garbage collection was already disabled.
-
.enable ⇒ Boolean
Enables garbage collection; returns whether garbage collection was disabled:
-
.latest_gc_info ⇒ Hash
With no argument given, returns information about the most recent garbage collection:
-
.start(full_mark: true, immediate_mark: true, immediate_sweep: true, global: true)
Initiates garbage collection, even if explicitly disabled by .disable.
-
.stat(process: false) ⇒ Hash
This method is implementation-specific to CRuby.
-
.stat_heap ⇒ Hash
This method is implementation-specific to CRuby.
-
.total_time ⇒ Integer
Returns the GC total time in nanoseconds:
Instance Method Summary
Class Attribute Details
.measure_total_time ⇒ Boolean (rw)
Returns the setting for GC total time measurement in the current
Ractor; the main Ractor's initial setting is true and, with the
default GC, other Ractors inherit their creator's setting.
See .total_time.
# File 'gc.rb', line 661
def self.measure_total_time Primitive.cexpr! %{ RBOOL(rb_gc_impl_get_measure_total_time(rb_gc_get_objspace())) } end
.measure_total_time=(setting) ⇒ setting (rw)
Enables or disables GC total time measurement;
returns setting.
See .total_time.
When argument object is nil or false, disables total time measurement;
.measure_total_time then returns false:
GC.measure_total_time = nil # => nil
GC.measure_total_time # => false
GC.measure_total_time = false # => false
GC.measure_total_time # => false
Otherwise, enables total time measurement;
.measure_total_time then returns true:
GC.measure_total_time = true # => true
GC.measure_total_time # => true
GC.measure_total_time = :foo # => :foo
GC.measure_total_time # => true
Note that when enabled, total time measurement affects performance.
The setting is per-Ractor: it affects only the ::Ractor that sets it.
With the default GC, a ::Ractor created by Ractor.new inherits the
setting of the ::Ractor that creates it; the main ::Ractor starts with
measurement enabled.
# File 'gc.rb', line 647
def self.measure_total_time=(flag) Primitive.cstmt! %{ rb_gc_impl_set_measure_total_time(rb_gc_get_objspace(), flag); return flag; } end
.stress ⇒ setting (rw)
Returns the current GC stress-mode setting,
which initially is false.
The stress mode may be set by method .stress=.
# File 'gc.rb', line 109
def self.stress Primitive.gc_stress_get end
.stress=(value) ⇒ value (rw)
Enables or disables stress mode. Stress mode causes GC to be invoked at every GC opportunity (all memory and object allocations); it is intended only for debugging and severely degrades performance.
Sets the current GC stress mode to the given value:
- If the value is
nilorfalse, disables stress mode. - If the value is an integer, enables stress mode with certain flags; see below.
- Otherwise, enables stress mode without any flags.
The flags are bits in the given integer:
0x01: no major GC.0x02: no immediate sweep.0x04: full mark after malloc/calloc/realloc.
# File 'gc.rb', line 134
def self.stress=(flag) Primitive.gc_stress_set_m flag end
Class Method Details
This method is implementation-specific to CRuby.
Sets or gets information about the current GC configuration.
Configuration parameters are GC implementation-specific and may change without notice.
With no argument given, returns a hash containing the configuration:
GC.config
# => {rgengc_allow_full_mark: true, implementation: "default"}
With argument hash_to_merge given,
merges that hash into the stored configuration hash;
ignores unknown hash keys;
returns the configuration hash:
GC.config(rgengc_allow_full_mark: false)
# => {rgengc_allow_full_mark: false, implementation: "default"}
GC.config(foo: 'bar')
# => {rgengc_allow_full_mark: false, implementation: "default"}
All-Implementations Configuration
The single read-only entry for all implementations is:
:implementation: the string name of the implementation; for the Ruby default implementation, 'default'.
Implementation-Specific Configuration
A GC implementation maintains its own implementation-specific configuration.
For Ruby's default implementation the single entry is:
-
:rgengc_allow_full_mark: Controls whether the GC is allowed to run a full mark (young & old objects): -
true(default): GC interleaves major and minor collections. A flag is set to notify GC that a full mark has been requested. This flag is accessible via GC.latest_gc_info(:need_major_by). -
false: GC does not initiate a full marking cycle unless explicitly directed by user code; see GC.start. Setting this parameter tofalsedisables young-to-old promotion. For performance reasons, we recommended warming up the application using Process.warmup before setting this parameter tofalse.
# File 'gc.rb', line 550
def self.config hash = nil if Primitive.cexpr!("RBOOL(RB_TYPE_P(hash, T_HASH))") if hash.include?(:implementation) raise ArgumentError, 'Attempting to set read-only key "Implementation"' end Primitive.gc_config_set hash elsif hash != nil raise ArgumentError end Primitive.gc_config_get end
.count ⇒ Integer
Returns the total number of times garbage collection has occurred:
With the default GC, counts the collections of the current Ractor's heap,
including global collections that other Ractors started.
GC.count # => 385
GC.start
GC.count # => 386
# File 'gc.rb', line 150
def self.count Primitive.gc_count end
.disable ⇒ Boolean
# File 'gc.rb', line 98
def self.disable Primitive.gc_disable end
.enable ⇒ Boolean
Enables garbage collection; returns whether garbage collection was disabled:
GC.disable
GC.enable # => true
GC.enable # => false
# File 'gc.rb', line 84
def self.enable Primitive.gc_enable end
With no argument given, returns information about the most recent garbage collection:
GC.latest_gc_info
# =>
{major_by: :force,
need_major_by: nil,
gc_by: :method,
have_finalizer: false,
immediate_sweep: true,
state: :none,
weak_references_count: 0,
retained_weak_references_count: 0}
With symbol argument key given,
returns the value for that key:
GC.latest_gc_info(:gc_by) # => :newobj
With hash argument hash given,
returns that hash with GC information merged into its content;
this form may be useful in minimizing probe effects:
h = {foo: 0, bar: 1}
GC.latest_gc_info(h)
# =>
{foo: 0,
bar: 1,
major_by: nil,
need_major_by: nil,
gc_by: :newobj,
have_finalizer: false,
immediate_sweep: false,
state: :sweeping,
weak_references_count: 0,
retained_weak_references_count: 0}
# File 'gc.rb', line 606
def self.latest_gc_info hash_or_key = nil if hash_or_key == nil hash_or_key = {} elsif Primitive.cexpr!("RBOOL(!SYMBOL_P(hash_or_key) && !RB_TYPE_P(hash_or_key, T_HASH))") raise TypeError, "non-hash or symbol given" end Primitive.cstmt! %{ return rb_gc_latest_gc_info(hash_or_key); } end
.start(full_mark: true, immediate_mark: true, immediate_sweep: true, global: true)
Initiates garbage collection, even if explicitly disabled by .disable.
Keyword arguments:
-
full_mark: a boolean value specifying whether to perform a major garbage collection cycle: -
true: initiates a major garbage collection cycle, meaning all objects (old and new) are marked. When another Ractor's object space exists (a live Ractor, or a terminated one not yet absorbed), or one was absorbed since the last global collection, andglobalistrue(the default), the cycle is a global collection instead; seeglobal. -
false: initiates a minor garbage collection cycle, meaning only young objects are marked. -
immediate_mark: a boolean value specifying whether marking is performed incrementally: -
true: marking is completed before the method returns. -
false: marking is performed in parts, interleaved with program execution both before the method returns and afterward; therefore marking may not be completed before the return. Note that iffull_markisfalse, marking is always immediate, regardless of the value ofimmediate_mark. -
immediate_sweep: a boolean value specifying whether sweeping is deferred (lazy sweep): -
true: sweeping is completed before the method returns. -
false: sweeping is performed in parts, interleaved with program execution both before the method returns and afterward; therefore sweeping may not be completed before the return. -
global: a boolean value specifying, when another Ractor's object space exists, whether to collect every Ractor's heap together in a single stop-the-world mark/sweep cycle: -
true: with another Ractor's object space present (seefull_mark) it runs a stop-the-world cycle and reclaims shareable and cross-Ractor garbage. This option, although it defaults totrue, is ignored unlessfull_mark,immediate_markandimmediate_sweepare alltrue. With a single object space it has no effect and the other options apply as usual. This option is also ignored unless you're using the default GC. -
false: collect only the calling Ractor's own objects. Shareable objects and cross-ractor garbage are not swept.
GC.stat counts a local major collection under :major_gc_count and a local
minor collection under :minor_gc_count. A global collection counts under
:global_gc_count in every Ractor whose heap it collects, and under
:global_gc_invocation_count in the calling Ractor.
Note that these keyword arguments are implementation- and version-dependent, are not guaranteed to be future-compatible, and may be ignored in some implementations.
# File 'gc.rb', line 65
def self.start full_mark: true, immediate_mark: true, immediate_sweep: true, global: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false, global end
This method is implementation-specific to CRuby.
Returns GC statistics. The particular statistics are implementation-specific and may change in the future without notice.
With process: false (the default) or nil,
returns statistics for the current Ractor's object space.
With any other value of process, returns process-wide statistics;
see "Process statistics" below.
With no positional argument or nil given,
returns a hash containing the GC statistics:
GC.stat
# =>
{count: 1,
time: 0,
marking_time: 0,
sweeping_time: 0,
total_malloc_bytes: 10432791,
total_free_bytes: 6989873,
heap_allocated_pages: 41,
heap_empty_pages: 0,
heap_allocatable_bytes: 228656,
heap_eden_pages: 41,
total_allocated_pages: 41,
total_freed_pages: 0,
malloc_increase_bytes: 0,
malloc_increase_bytes_limit: 16777216,
minor_gc_count: 0,
major_gc_count: 1,
global_gc_count: 0,
global_gc_invocation_count: 0,
compact_count: 0,
read_barrier_faults: 0,
total_moved_objects: 0,
remembered_wb_unprotected_objects: 0,
remembered_wb_unprotected_objects_limit: 7,
old_objects: 721,
old_objects_limit: 1442,
oldmalloc_increase_bytes: 0,
oldmalloc_increase_bytes_limit: 16777216,
total_allocated_objects: 36735,
total_freed_objects: 19527,
heap_available_slots: 40591,
heap_live_slots: 17208,
heap_free_slots: 23383,
heap_final_slots: 0,
heap_marked_slots: 17175}
With symbol argument key given,
returns the value for that key:
GC.stat(:count) # => 30
With hash argument hash given,
returns that hash with GC statistics merged into its content;
this form may be useful in minimizing probe effects:
h = {foo: 0, bar: 1}
GC.stat(h)
h.keys.take(5) # => [:foo, :bar, :count, :time, :marking_time]
The hash includes entries such as:
:count: The total number of garbage collections of this Ractor's heap since the object space was created. It includes minor, major, and global garbage collections, and equals:minor_gc_countplus:major_gc_countplus:global_gc_count.:time: The total time spent in garbage collections (in milliseconds).:marking_time: The total time spent marking objects (in milliseconds).:sweeping_time: The total time spent sweeping objects (in milliseconds).:total_malloc_bytes: The total number of bytes allocated by malloc since application start.:total_free_bytes: The total number of bytes freed since application start.:heap_allocated_pages: The total number of allocated pages.:heap_empty_pages: The number of pages with no live objects, and that could be released to the system.:heap_allocatable_bytes: The number of bytes that can be allocated without triggering a new garbage collection cycle.:heap_eden_pages: The total number of pages which contain at least one live slot.:total_allocated_pages: The cumulative number of pages allocated since application start.:total_freed_pages: The cumulative number of pages freed since application start.:malloc_increase_bytes: Amount of memory allocated on the heap for objects. Decreased by any GC.:malloc_increase_bytes_limit: When:malloc_increase_bytescrosses this limit, GC is triggered.:minor_gc_count: The total number of local minor garbage collections of this Ractor's heap.:major_gc_count: The total number of local major garbage collections of this Ractor's heap. Global garbage collections are counted separately.:global_gc_count: The number of global (stop-the-world) garbage collections that collected this Ractor's heap. Any Ractor can start them.:global_gc_invocation_count: The number of global garbage collections that this Ractor started. Each global garbage collection has exactly one starter.:compact_count: The total number of compactions run since process start.:read_barrier_faults: The total number of times the read barrier was triggered during compaction.:total_moved_objects: The total number of objects compaction has moved.:remembered_wb_unprotected_objects: The total number of objects without write barriers.:remembered_wb_unprotected_objects_limit: When:remembered_wb_unprotected_objectscrosses this limit, major GC is triggered.:old_objects: Number of live, old objects which have survived at least 3 garbage collections.:old_objects_limit: When:old_objectscrosses this limit, major GC is triggered.:oldmalloc_increase_bytes: Amount of memory allocated on the heap for objects. Decreased by major GC.:oldmalloc_increase_bytes_limit: When:oldmalloc_increase_bytescrosses this limit, major GC is triggered.:total_allocated_objects: The cumulative number of objects allocated since application start.:total_freed_objects: The cumulative number of objects freed since application start.:heap_available_slots: The total number of slots in all:heap_allocated_pages.:heap_live_slots: The total number of slots which contain live objects.:heap_free_slots: The total number of slots which do not contain live objects.:heap_final_slots: The total number of slots with pending finalizers to be run.:heap_marked_slots: The number of objects in this Ractor's heap marked in the last GC of that heap.
Process statistics
With process: true, the default collector reports cumulative collection counts and measured CPU time across all Ractors, retaining history from destroyed object spaces, and the state of the page pool that all object spaces share:
GC.stat(process: true)
# => {count: 42, time: 3, marking_time: 2, sweeping_time: 1,
# minor_gc_count: 32, major_gc_count: 8, global_gc_count: 2,
# page_pool_arenas: 2, page_pool_arenas_freed: 0,
# page_pool_total_pages: 64, page_pool_discarded_pages: 0}
:count is the number of garbage collections in the process. Each local
and each global collection counts once, so :count equals
:minor_gc_count plus :major_gc_count plus :global_gc_count. It is not
the sum of the ::Ractor :count values, because one global collection
collects every heap.
:global_gc_count is the number of global collections in the process,
however many Ractors each one stops.
The page pool keys are:
:page_pool_arenas: The number of page-pool arenas that are mapped now.:page_pool_arenas_freed: The number of arenas that the page pool has unmapped.:page_pool_total_pages: The number of page bodies in the mapped arenas.:page_pool_discarded_pages: The number of free page bodies whose memory the page pool has returned to the operating system.
:time may exceed :marking_time plus :sweeping_time by one millisecond
because raw nanoseconds are summed before conversion. Times measure collector
CPU work, not wall-clock pauses.
Reads combine object-space publications without requesting a stop-the-world
barrier. .measure_total_time controls future timing accumulation. Profiler
controls do not affect these totals. A forked child inherits its parent's
totals. MMTk and wbcheck raise ::NotImplementedError for process statistics.
Unavailable keys raise ::ArgumentError.
# File 'gc.rb', line 347
def self.stat hash_or_key = nil, process: false Primitive.gc_stat hash_or_key, process end
This method is implementation-specific to CRuby.
Returns statistics for GC heaps. The particular statistics are implementation-specific and may change in the future without notice.
With no argument given, returns statistics for all heaps:
GC.stat_heap
# =>
{0 =>
{slot_size: 32,
heap_eden_pages: 24,
heap_eden_slots: 12288,
total_allocated_pages: 24,
force_major_gc_count: 0,
force_incremental_marking_finish_count: 0,
total_allocated_objects: 8450,
total_freed_objects: 3120},
1 =>
{slot_size: 64,
heap_eden_pages: 246,
heap_eden_slots: 402802,
total_allocated_pages: 246,
force_major_gc_count: 2,
force_incremental_marking_finish_count: 1,
total_allocated_objects: 33867152,
total_freed_objects: 33520523},
2 =>
{slot_size: 128,
heap_eden_pages: 84,
heap_eden_slots: 68746,
total_allocated_pages: 84,
force_major_gc_count: 1,
force_incremental_marking_finish_count: 4,
total_allocated_objects: 147491,
total_freed_objects: 90699},
3 =>
{slot_size: 256,
heap_eden_pages: 157,
heap_eden_slots: 64182,
total_allocated_pages: 157,
force_major_gc_count: 0,
force_incremental_marking_finish_count: 0,
total_allocated_objects: 211460,
total_freed_objects: 190075},
4 =>
{slot_size: 512,
heap_eden_pages: 8,
heap_eden_slots: 1631,
total_allocated_pages: 8,
force_major_gc_count: 0,
force_incremental_marking_finish_count: 0,
total_allocated_objects: 1422,
total_freed_objects: 700},
5 =>
{slot_size: 1024,
heap_eden_pages: 16,
heap_eden_slots: 1628,
total_allocated_pages: 16,
force_major_gc_count: 0,
force_incremental_marking_finish_count: 0,
total_allocated_objects: 1230,
total_freed_objects: 309}}
In the example above, the keys in the outer hash are the heap identifiers:
GC.stat_heap.keys # => [0, 1, 2, 3, 4, 5]
On CRuby, each heap identifier is an integer; on other implementations, a heap identifier may be a string.
With only argument heap_id given,
returns statistics for the given heap identifier:
GC.stat_heap(3)
# =>
{slot_size: 256,
heap_eden_pages: 157,
heap_eden_slots: 64182,
total_allocated_pages: 157,
force_major_gc_count: 0,
force_incremental_marking_finish_count: 0,
total_allocated_objects: 225018,
total_freed_objects: 206647}
With arguments heap_id and key given,
returns the value for the given key in the given heap:
GC.stat_heap(3, :slot_size) # => 256
With arguments nil and hash given,
merges the statistics for all heaps into the given hash:
h = {foo: 0, bar: 1}
GC.stat_heap(nil, h).keys # => [:foo, :bar, 0, 1, 2, 3, 4]
With arguments heap_id and hash given,
merges the statistics for the given heap into the given hash:
h = {foo: 0, bar: 1}
GC.stat_heap(2, h).keys
# =>
[:foo,
:,
:slot_size,
:heap_eden_pages,
:heap_eden_slots,
:total_allocated_pages,
:force_major_gc_count,
:force_incremental_marking_finish_count,
:total_allocated_objects,
:total_freed_objects]
The statistics for a heap may include:
:slot_size: The slot size of the heap in bytes.:heap_allocatable_pages: The number of pages that can be allocated without triggering a new garbage collection cycle.:heap_eden_pages: The number of pages in the eden heap.:heap_eden_slots: The total number of slots in all of the pages in the eden heap.:total_allocated_pages: The total number of pages that have been allocated in the heap.:total_freed_pages: The total number of pages that have been freed and released back to the system in the heap.:force_major_gc_count: The number of times this heap has forced major garbage collection cycles to start due to running out of free slots.:force_incremental_marking_finish_count: The number of times this heap has forced incremental marking to complete due to running out of pooled slots.
# File 'gc.rb', line 495
def self.stat_heap heap_name = nil, hash_or_key = nil Primitive.gc_stat_heap heap_name, hash_or_key end
.total_time ⇒ Integer
Returns the GC total time in nanoseconds:
With the default collector, this is the current Ractor's measured GC CPU
work, not wall-clock pause time.
GC.total_time # => 156250
Note that total time accumulates
only when total time measurement is enabled
(that is, when .measure_total_time is true):
GC.measure_total_time # => true
GC.total_time # => 625000
GC.start
GC.total_time # => 937500
GC.start
GC.total_time # => 1093750
GC.measure_total_time = false
GC.total_time # => 1250000
GC.start
GC.total_time # => 1250000
GC.start
GC.total_time # => 1250000
GC.measure_total_time = true
GC.total_time # => 1250000
GC.start
GC.total_time # => 1406250
# File 'gc.rb', line 700
def self.total_time Primitive.cexpr! %{ ULL2NUM(rb_gc_impl_get_total_time(rb_gc_get_objspace())) } end
Instance Method Details
#garbage_collect(full_mark: true, immediate_mark: true, immediate_sweep: true, global: true)
Alias of .start
# File 'gc.rb', line 70
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true, global: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false, global end