# for gc.c # 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. module GC # Initiates garbage collection, even if explicitly disabled by GC.disable. # # Keyword arguments: # # - +full_mark+: # its boolean value determines whether to perform a major garbage collection cycle: # # - +true+: initiates a major garbage collection cycle, # meaning all objects (old and new) are marked. # - +false+: initiates a minor garbage collection cycle, # meaning only young objects are marked. # # - +immediate_mark+: # its boolean value determines whether to perform incremental marking: # # - +true+: marking is completed before the method returns. # - +false+: marking is performed by parts, # interleaved with program execution both before the method returns and afterward; # therefore marking may not be completed before the return. # Note that if +full_mark+ is +false+, marking will always be immediate, # regardless of the value of +immediate_mark+. # # - +immediate_sweep+: # its boolean value determines whether to defer sweeping (using lazy sweep): # # - +true+: sweeping is completed before the method returns. # - +false+: sweeping is performed by parts, # interleaved with program execution both before the method returns and afterward; # therefore sweeping may not be completed before the return. # # Note that these keword arguments are implementation- and version-dependent, # are not guaranteed to be future-compatible, # and may be ignored in some implementations. def self.start full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end # Alias of GC.start def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end # call-seq: # GC.enable -> true or false # # Enables garbage collection; # returns whether garbage collection was disabled: # # GC.disable # GC.enable # => true # GC.enable # => false # def self.enable Primitive.gc_enable end # call-seq: # GC.disable -> true or false # # Disables garbage collection (but GC.start remains potent): # returns whether garbage collection was already disabled. # # GC.enable # GC.disable # => false # GC.disable # => true # def self.disable Primitive.gc_disable end # call-seq: # GC.stress -> setting # # Returns the current \GC stress-mode setting, # which initially is +false+. # # The stress mode may be set by method GC.stress=. def self.stress Primitive.gc_stress_get end # call-seq: # GC.stress = value -> value # # Enables or disables stress mode; # enabling stress mode will degrade performance; it is only for debugging. # # Sets the current \GC stress mode to the given value: # # - If the value is +nil+ or +false+, disables stress mode. # - If the value is an integer, # enables stress mode with certain flags; see below. # - Otherwise, enables stress mode; # \GC is invoked at every \GC opportunity: all memory and object allocations. # # The flags are bits in the given integer: # # - +0x01+: No major \GC. # - +0x02+: No immediate sweep. # - +0x04+: Full mark after malloc/calloc/realloc. # def self.stress=(flag) Primitive.gc_stress_set_m flag end # call-seq: # self.count -> integer # # Returns the total number of times garbage collection has occurred: # # GC.count # => 385 # GC.start # GC.count # => 386 # def self.count Primitive.gc_count end # call-seq: # GC.stat -> new_hash # GC.stat(key) -> value # GC.stat(hash) -> hash # # 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 no argument given, # returns information about the most recent garbage collection: # # GC.stat # # => # {count: 28, # time: 1, # marking_time: 1, # sweeping_time: 0, # heap_allocated_pages: 521, # heap_empty_pages: 0, # heap_allocatable_slots: 0, # heap_available_slots: 539590, # heap_live_slots: 422243, # heap_free_slots: 117347, # heap_final_slots: 0, # heap_marked_slots: 264877, # heap_eden_pages: 521, # total_allocated_pages: 521, # total_freed_pages: 0, # total_allocated_objects: 2246376, # total_freed_objects: 1824133, # malloc_increase_bytes: 50982, # malloc_increase_bytes_limit: 18535172, # minor_gc_count: 18, # major_gc_count: 10, # compact_count: 0, # read_barrier_faults: 0, # total_moved_objects: 0, # remembered_wb_unprotected_objects: 0, # remembered_wb_unprotected_objects_limit: 2162, # old_objects: 216365, # old_objects_limit: 432540, # oldmalloc_increase_bytes: 1654232, # oldmalloc_increase_bytes_limit: 16846103} # # 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}[https://en.wikipedia.org/wiki/Probe_effect]: # # 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 run since application start # (count includes both minor and major garbage collections). # - +:time+: # The total time spent in garbage collections (in milliseconds). # - +:heap_allocated_pages+: # The total number of +:heap_eden_pages+ + +:heap_tomb_pages+. # - +:heap_sorted_length+: # The number of pages that can fit into the buffer that holds references to all pages. # - +:heap_allocatable_pages+: # The total number of pages the application could allocate without additional \GC. # - +: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 total number of objects marked in the last \GC. # - +:heap_eden_pages+: # The total number of pages which contain at least one live slot. # - +:heap_tomb_pages+: # The total number of pages which do not contain any live slots. # - +:total_allocated_pages+: # The cumulative number of pages allocated since application start. # - +:total_freed_pages+: # The cumulative number of pages freed since application start. # - +:total_allocated_objects+: # The cumulative number of objects allocated since application start. # - +:total_freed_objects+: # The cumulative number of objects 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_bytes+ crosses this limit, \GC is triggered. # - +:minor_gc_count+: # The total number of minor garbage collections run since process start. # - +:major_gc_count+: # The total number of major garbage collections run since process start. # - +: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_objects+ crosses 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_objects+ crosses 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_bytes+ crosses this limit, major \GC is triggered. # def self.stat hash_or_key = nil Primitive.gc_stat hash_or_key end # call-seq: # GC.stat_heap -> Hash # GC.stat_heap(nil, hash) -> Hash # GC.stat_heap(heap_name) -> Hash # GC.stat_heap(heap_name, hash) -> Hash # GC.stat_heap(heap_name, :key) -> Numeric # # Returns information for heaps in the \GC. # # If the first optional argument, +heap_name+, is passed in and not +nil+, it # returns a +Hash+ containing information about the particular heap. # Otherwise, it will return a +Hash+ with heap names as keys and # a +Hash+ containing information about the heap as values. # # If the second optional argument, +hash_or_key+, is given as a +Hash+, it will # be overwritten and returned. This is intended to avoid the probe effect. # # If both optional arguments are passed in and the second optional argument is # a symbol, it will return a +Numeric+ value for the particular heap. # # On CRuby, +heap_name+ is of the type +Integer+ but may be of type +String+ # on other implementations. # # The contents of the hash are implementation-specific and may change in # the future without notice. # # If the optional argument, hash, is given, it is overwritten and returned. # # This method is only expected to work on CRuby. # # The hash includes the following keys about the internal information in # the \GC: # # [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. # [heap_tomb_pages] # The number of pages in the tomb heap. The tomb heap only contains pages # that do not have any live objects. # [heap_tomb_slots] # The total number of slots in all of the pages in the tomb 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. # def self.stat_heap heap_name = nil, hash_or_key = nil Primitive.gc_stat_heap heap_name, hash_or_key end # call-seq: # GC.config -> hash # GC.config(hash_to_merge) -> hash # # 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 to +false+ disables young-to-old promotion. # For performance reasons, we recommended warming up the application using Process.warmup # before setting this parameter to +false+. # 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 # call-seq: # GC.latest_gc_info -> new_hash # GC.latest_gc_info(key) -> value # GC.latest_gc_info(hash) -> hash # # 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}[https://en.wikipedia.org/wiki/Probe_effect]: # # 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} # 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 # call-seq: # GC.measure_total_time = setting -> setting # # Enables or disables \GC total time measurement; # returns +setting+. # See GC.total_time. # # When argument +object+ is +nil+ or +false+, disables total time measurement; # GC.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; # GC.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. def self.measure_total_time=(flag) Primitive.cstmt! %{ rb_gc_impl_set_measure_total_time(rb_gc_get_objspace(), flag); return flag; } end # call-seq: # GC.measure_total_time -> true or false # # Returns the setting for \GC total time measurement; # the initial setting is +true+. # See GC.total_time. def self.measure_total_time Primitive.cexpr! %{ RBOOL(rb_gc_impl_get_measure_total_time(rb_gc_get_objspace())) } end # call-seq: # GC.total_time -> integer # # Returns the \GC total time in nanoseconds: # # GC.total_time # => 156250 # # Note that total time accumulates # only when total time measurement is enabled # (that is, when GC.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 # def self.total_time Primitive.cexpr! %{ ULL2NUM(rb_gc_impl_get_total_time(rb_gc_get_objspace())) } end end module ObjectSpace # Alias of GC.start def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end module_function :garbage_collect end