GC
module GC
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.
Constants
- INTERNAL_CONSTANTS
- OPTS
Public Class Methods
Disables garbage collection, returning true
if garbage collection was already disabled.
GC.disable #=> false GC.disable #=> true
VALUE rb_gc_disable(void) { rb_objspace_t *objspace = &rb_objspace; int old = dont_gc; gc_rest(objspace); dont_gc = TRUE; return old ? Qtrue : Qfalse; }
Enables garbage collection, returning true
if garbage collection was previously disabled.
GC.disable #=> false GC.enable #=> true GC.enable #=> false
VALUE rb_gc_enable(void) { rb_objspace_t *objspace = &rb_objspace; int old = dont_gc; dont_gc = FALSE; return old ? Qtrue : Qfalse; }
Returns information about the most recent garbage collection.
static VALUE gc_latest_gc_info(int argc, VALUE *argv, VALUE self) { rb_objspace_t *objspace = &rb_objspace; VALUE arg = Qnil; if (rb_scan_args(argc, argv, "01", &arg) == 1) { if (!SYMBOL_P(arg) && !RB_TYPE_P(arg, T_HASH)) { rb_raise(rb_eTypeError, "non-hash or symbol given"); } } if (arg == Qnil) { arg = rb_hash_new(); } return gc_info_decode(objspace, arg, 0); }
Returns the size of memory allocated by malloc().
Only available if ruby was built with CALC_EXACT_MALLOC_SIZE
.
static VALUE gc_malloc_allocated_size(VALUE self) { return UINT2NUM(rb_objspace.malloc_params.allocated_size); }
Returns the number of malloc() allocations.
Only available if ruby was built with CALC_EXACT_MALLOC_SIZE
.
static VALUE gc_malloc_allocations(VALUE self) { return UINT2NUM(rb_objspace.malloc_params.allocations); }
Initiates garbage collection, unless manually disabled.
This method is defined with keyword arguments that default to true:
def GC.start(full_mark: true, immediate_sweep: true); end
Use full_mark: false to perform a minor GC- Use immediate_sweep: false to defer sweeping (use lazy sweep)-
Note: These keyword arguments are implementation and version dependent- They are not guaranteed to be future-compatible, and may be ignored if the underlying implementation does not support them-
static VALUE gc_start_internal(int argc, VALUE *argv, VALUE self) { rb_objspace_t *objspace = &rb_objspace; int full_mark = TRUE, immediate_mark = TRUE, immediate_sweep = TRUE; VALUE opt = Qnil; static ID keyword_ids[3]; rb_scan_args(argc, argv, "0:", &opt); if (!NIL_P(opt)) { VALUE kwvals[3]; if (!keyword_ids[0]) { keyword_ids[0] = rb_intern("full_mark"); keyword_ids[1] = rb_intern("immediate_mark"); keyword_ids[2] = rb_intern("immediate_sweep"); } rb_get_kwargs(opt, keyword_ids, 0, 3, kwvals); if (kwvals[0] != Qundef) full_mark = RTEST(kwvals[0]); if (kwvals[1] != Qundef) immediate_mark = RTEST(kwvals[1]); if (kwvals[2] != Qundef) immediate_sweep = RTEST(kwvals[2]); } garbage_collect(objspace, full_mark, immediate_mark, immediate_sweep, GPR_FLAG_METHOD); if (!finalizing) finalize_deferred(objspace); return Qnil; }
Returns a Hash containing information about the GC-
The hash includes information about internal statistics about GC such as:
{ :count=>0, :heap_allocated_pages=>24, :heap_sorted_length=>24, :heap_allocatable_pages=>0, :heap_available_slots=>9783, :heap_live_slots=>7713, :heap_free_slots=>2070, :heap_final_slots=>0, :heap_marked_slots=>0, :heap_swept_slots=>0, :heap_eden_pages=>24, :heap_tomb_pages=>0, :total_allocated_pages=>24, :total_freed_pages=>0, :total_allocated_objects=>7796, :total_freed_objects=>83, :malloc_increase_bytes=>2389312, :malloc_increase_bytes_limit=>16777216, :minor_gc_count=>0, :major_gc_count=>0, :remembered_wb_unprotected_objects=>0, :remembered_wb_unprotected_objects_limit=>0, :old_objects=>0, :old_objects_limit=>0, :oldmalloc_increase_bytes=>2389760, :oldmalloc_increase_bytes_limit=>16777216 }
The contents of the hash are implementation specific and may be changed in the future.
This method is only expected to work on C Ruby.
static VALUE gc_stat(int argc, VALUE *argv, VALUE self) { VALUE arg = Qnil; if (rb_scan_args(argc, argv, "01", &arg) == 1) { if (SYMBOL_P(arg)) { size_t value = gc_stat_internal(arg); return SIZET2NUM(value); } else if (!RB_TYPE_P(arg, T_HASH)) { rb_raise(rb_eTypeError, "non-hash or symbol given"); } } if (arg == Qnil) { arg = rb_hash_new(); } gc_stat_internal(arg); return arg; }
Returns current status of GC stress mode-
static VALUE gc_stress_get(VALUE self) { rb_objspace_t *objspace = &rb_objspace; return ruby_gc_stress_mode; }
Updates the GC stress mode-
When stress mode is enabled, the GC is invoked at every GC opportunity: all memory and object allocations-
Enabling stress mode will degrade performance, it is only for debugging-
flag can be true, false, or a fixnum bit-ORed following flags-
0x01:: no major GC 0x02:: no immediate sweep 0x04:: full mark after malloc/calloc/realloc
static VALUE gc_stress_set_m(VALUE self, VALUE flag) { rb_objspace_t *objspace = &rb_objspace; rb_secure(2); gc_stress_set(objspace, flag); return flag; }
Verify internal consistency.
This method is implementation specific. Now this method checks generational consistency if RGenGC is supported.
static VALUE gc_verify_internal_consistency(VALUE self) { rb_objspace_t *objspace = &rb_objspace; struct verify_internal_consistency_struct data = {0}; struct each_obj_args eo_args; data.objspace = objspace; gc_report(5, objspace, "gc_verify_internal_consistency: start\n"); /* check relations */ eo_args.callback = verify_internal_consistency_i; eo_args.data = (void *)&data; objspace_each_objects((VALUE)&eo_args); if (data.err_count != 0) { #if RGENGC_CHECK_MODE >= 5 objspace->rgengc.error_count = data.err_count; gc_marks_check(objspace, NULL, NULL); allrefs_dump(objspace); #endif rb_bug("gc_verify_internal_consistency: found internal inconsistency."); } /* check heap_page status */ gc_verify_heap_pages(objspace); /* check counters */ if (!is_lazy_sweeping(heap_eden) && !finalizing) { if (objspace_live_slots(objspace) != data.live_object_count) { fprintf(stderr, "heap_pages_final_slots: %d, objspace->profile.total_freed_objects: %d\n", (int)heap_pages_final_slots, (int)objspace->profile.total_freed_objects); rb_bug("inconsistent live slot nubmer: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace_live_slots(objspace), data.live_object_count); } } #if USE_RGENGC if (!is_marking(objspace)) { if (objspace->rgengc.old_objects != data.old_object_count) { rb_bug("inconsistent old slot nubmer: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.old_objects, data.old_object_count); } if (objspace->rgengc.remembered_wb_unprotected_objects != data.remembered_shady_count) { rb_bug("inconsistent old slot nubmer: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.remembered_wb_unprotected_objects, data.remembered_shady_count); } } #endif if (!finalizing) { size_t list_count = 0; { VALUE z = heap_pages_deferred_final; while (z) { list_count++; z = RZOMBIE(z)->next; } } if (heap_pages_final_slots != data.zombie_object_count || heap_pages_final_slots != list_count) { rb_bug("inconsistent finalizing object count:\n" " expect %"PRIuSIZE"\n" " but %"PRIuSIZE" zombies\n" " heap_pages_deferred_final list has %"PRIuSIZE" items.", heap_pages_final_slots, data.zombie_object_count, list_count); } } gc_report(5, objspace, "gc_verify_internal_consistency: OK\n"); return Qnil; }
Public Instance Methods
Initiates garbage collection, unless manually disabled.
This method is defined with keyword arguments that default to true:
def GC.start(full_mark: true, immediate_sweep: true); end
Use full_mark: false to perform a minor GC- Use immediate_sweep: false to defer sweeping (use lazy sweep)-
Note: These keyword arguments are implementation and version dependent- They are not guaranteed to be future-compatible, and may be ignored if the underlying implementation does not support them-
static VALUE gc_start_internal(int argc, VALUE *argv, VALUE self) { rb_objspace_t *objspace = &rb_objspace; int full_mark = TRUE, immediate_mark = TRUE, immediate_sweep = TRUE; VALUE opt = Qnil; static ID keyword_ids[3]; rb_scan_args(argc, argv, "0:", &opt); if (!NIL_P(opt)) { VALUE kwvals[3]; if (!keyword_ids[0]) { keyword_ids[0] = rb_intern("full_mark"); keyword_ids[1] = rb_intern("immediate_mark"); keyword_ids[2] = rb_intern("immediate_sweep"); } rb_get_kwargs(opt, keyword_ids, 0, 3, kwvals); if (kwvals[0] != Qundef) full_mark = RTEST(kwvals[0]); if (kwvals[1] != Qundef) immediate_mark = RTEST(kwvals[1]); if (kwvals[2] != Qundef) immediate_sweep = RTEST(kwvals[2]); } garbage_collect(objspace, full_mark, immediate_mark, immediate_sweep, GPR_FLAG_METHOD); if (!finalizing) finalize_deferred(objspace); return Qnil; }
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.