Module: GC
- Defined in:
- (unknown)
Defined Under Namespace
Modules: Profiler
Constant Summary collapse
- OPTS =
GC build options
opts = rb_ary_new()
- INTERNAL_CONSTANTS =
Internal constants in the garbage collector.
gc_constants
Class Method Summary collapse
-
.add_stress_to_class ⇒ Object
Raises NoMemoryError when allocating an instance of the given classes.
-
.auto_compact ⇒ Boolean
Returns whether or not automatic compaction has been enabled.
-
.auto_compact=(flag) ⇒ Object
Updates automatic compaction mode.
-
.compact ⇒ Hash
This function compacts objects together in Ruby's heap.
-
.latest_compact_info ⇒ Hash
Returns information about object moved in the most recent GC compaction.
-
.malloc_allocated_size ⇒ Integer
Returns the size of memory allocated by malloc().
-
.malloc_allocations ⇒ Integer
Returns the number of malloc() allocations.
-
.remove_stress_to_class ⇒ Object
No longer raises NoMemoryError when allocating an instance of the given classes.
-
.verify_compaction_references(toward: nil, double_heap: false) ⇒ Hash
Verify compaction reference consistency.
-
.verify_internal_consistency ⇒ nil
Verify internal consistency.
Class Method Details
.add_stress_to_class ⇒ Object
Raises NoMemoryError when allocating an instance of the given classes.
9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 |
# File 'ext/gc-4.0/gc/default/default.c', line 9437
static VALUE
rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
{
rb_objspace_t *objspace = rb_gc_get_objspace();
if (!stress_to_class) {
set_stress_to_class(rb_ident_hash_new_with_size(argc));
}
for (int i = 0; i < argc; i++) {
VALUE klass = argv[i];
rb_hash_aset(stress_to_class, klass, Qtrue);
}
return self;
}
|
.auto_compact ⇒ Boolean
Returns whether or not automatic compaction has been enabled.
9093 9094 9095 9096 9097 |
# File 'ext/gc-4.0/gc/default/default.c', line 9093
static VALUE
gc_get_auto_compact(VALUE _)
{
return ruby_enable_autocompact ? Qtrue : Qfalse;
}
|
.auto_compact=(flag) ⇒ Object
Updates automatic compaction mode.
When enabled, the compactor will execute on every major collection.
Enabling compaction will degrade performance on major collections.
9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 |
# File 'ext/gc-4.0/gc/default/default.c', line 9062
static VALUE
gc_set_auto_compact(VALUE _, VALUE v)
{
GC_ASSERT(GC_COMPACTION_SUPPORTED);
ruby_enable_autocompact = RTEST(v);
#if RGENGC_CHECK_MODE
ruby_autocompact_compare_func = NULL;
if (SYMBOL_P(v)) {
ID id = RB_SYM2ID(v);
if (id == rb_intern("empty")) {
ruby_autocompact_compare_func = compare_free_slots;
}
}
#endif
return v;
}
|
.compact ⇒ Hash
This function compacts objects together in Ruby's heap. It eliminates unused space (or fragmentation) in the heap by moving objects in to that unused space.
The returned hash contains statistics about the objects that were moved;
see GC.latest_compact_info.
This method is only expected to work on CRuby.
To test whether GC compaction is supported, use the idiom:
GC.respond_to?(:compact)
9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 |
# File 'ext/gc-4.0/gc/default/default.c', line 9184
static VALUE
gc_compact(VALUE self)
{
rb_objspace_t *objspace = rb_gc_get_objspace();
int full_marking_p = gc_config_full_mark_val;
gc_config_full_mark_set(TRUE);
/* Run GC with compaction enabled */
rb_gc_impl_start(rb_gc_get_objspace(), true, true, true, true);
gc_config_full_mark_set(full_marking_p);
return gc_compact_stats(self);
}
|
.latest_compact_info ⇒ Hash
Returns information about object moved in the most recent GC compaction.
The returned hash contains the following keys:
[considered] Hash containing the type of the object as the key and the number of objects of that type that were considered for movement. [moved] Hash containing the type of the object as the key and the number of objects of that type that were actually moved. [moved_up] Hash containing the type of the object as the key and the number of objects of that type that were increased in size. [moved_down] Hash containing the type of the object as the key and the number of objects of that type that were decreased in size.
Some objects can't be moved (due to pinning) so these numbers can be used to calculate compaction efficiency.
9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 |
# File 'ext/gc-4.0/gc/default/default.c', line 9127
static VALUE
gc_compact_stats(VALUE self)
{
rb_objspace_t *objspace = rb_gc_get_objspace();
VALUE h = rb_hash_new();
VALUE considered = rb_hash_new();
VALUE moved = rb_hash_new();
VALUE moved_up = rb_hash_new();
VALUE moved_down = rb_hash_new();
for (size_t i = 0; i < T_MASK; i++) {
if (objspace->rcompactor.considered_count_table[i]) {
rb_hash_aset(considered, type_sym(i), SIZET2NUM(objspace->rcompactor.considered_count_table[i]));
}
if (objspace->rcompactor.moved_count_table[i]) {
rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i]));
}
if (objspace->rcompactor.moved_up_count_table[i]) {
rb_hash_aset(moved_up, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_up_count_table[i]));
}
if (objspace->rcompactor.moved_down_count_table[i]) {
rb_hash_aset(moved_down, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_down_count_table[i]));
}
}
rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered);
rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved);
rb_hash_aset(h, ID2SYM(rb_intern("moved_up")), moved_up);
rb_hash_aset(h, ID2SYM(rb_intern("moved_down")), moved_down);
return h;
}
|
.malloc_allocated_size ⇒ Integer
Returns the size of memory allocated by malloc().
Only available if ruby was built with CALC_EXACT_MALLOC_SIZE.
9381 9382 9383 9384 9385 9386 |
# File 'ext/gc-4.0/gc/default/default.c', line 9381
static VALUE
gc_malloc_allocated_size(VALUE self)
{
rb_objspace_t *objspace = (rb_objspace_t *)rb_gc_get_objspace();
return ULL2NUM(objspace->malloc_params.allocated_size);
}
|
.malloc_allocations ⇒ Integer
Returns the number of malloc() allocations.
Only available if ruby was built with CALC_EXACT_MALLOC_SIZE.
9397 9398 9399 9400 9401 9402 |
# File 'ext/gc-4.0/gc/default/default.c', line 9397
static VALUE
gc_malloc_allocations(VALUE self)
{
rb_objspace_t *objspace = (rb_objspace_t *)rb_gc_get_objspace();
return ULL2NUM(objspace->malloc_params.allocations);
}
|
.remove_stress_to_class ⇒ Object
No longer raises NoMemoryError when allocating an instance of the given classes.
9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 |
# File 'ext/gc-4.0/gc/default/default.c', line 9462
static VALUE
rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
{
rb_objspace_t *objspace = rb_gc_get_objspace();
if (stress_to_class) {
for (int i = 0; i < argc; ++i) {
rb_hash_delete(stress_to_class, argv[i]);
}
if (rb_hash_size(stress_to_class) == 0) {
stress_to_class = 0;
}
}
return Qnil;
}
|
.verify_compaction_references(toward: nil, double_heap: false) ⇒ Hash
Verify compaction reference consistency.
This method is implementation specific. During compaction, objects that were moved are replaced with T_MOVED objects. No object should have a reference to a T_MOVED object after compaction.
This function expands the heap to ensure room to move all objects, compacts the heap to make sure everything moves, updates all references, then performs a full GC. If any object contains a reference to a T_MOVED object, that object should be pushed on the mark stack, and will make a SEGV.
9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 |
# File 'ext/gc-4.0/gc/default/default.c', line 9245
static VALUE
gc_verify_compaction_references(int argc, VALUE* argv, VALUE self)
{
static ID keywords[3] = {0};
if (!keywords[0]) {
keywords[0] = rb_intern("toward");
keywords[1] = rb_intern("double_heap");
keywords[2] = rb_intern("expand_heap");
}
VALUE options;
rb_scan_args_kw(rb_keyword_given_p(), argc, argv, ":", &options);
VALUE arguments[3] = { Qnil, Qfalse, Qfalse };
int kwarg_count = rb_get_kwargs(options, keywords, 0, 3, arguments);
bool toward_empty = kwarg_count > 0 && SYMBOL_P(arguments[0]) && SYM2ID(arguments[0]) == rb_intern("empty");
bool expand_heap = (kwarg_count > 1 && RTEST(arguments[1])) || (kwarg_count > 2 && RTEST(arguments[2]));
rb_objspace_t *objspace = rb_gc_get_objspace();
/* Clear the heap. */
rb_gc_impl_start(objspace, true, true, true, false);
unsigned int lev = RB_GC_VM_LOCK();
{
gc_rest(objspace);
/* if both double_heap and expand_heap are set, expand_heap takes precedence */
if (expand_heap) {
struct desired_compaction_pages_i_data desired_compaction = {
.objspace = objspace,
.required_slots = {0},
};
/* Work out how many objects want to be in each size pool, taking account of moves */
objspace_each_pages(objspace, desired_compaction_pages_i, &desired_compaction, TRUE);
/* Find out which pool has the most pages */
size_t max_existing_pages = 0;
for (int i = 0; i < HEAP_COUNT; i++) {
rb_heap_t *heap = &heaps[i];
max_existing_pages = MAX(max_existing_pages, heap->total_pages);
}
/* Add pages to each size pool so that compaction is guaranteed to move every object */
for (int i = 0; i < HEAP_COUNT; i++) {
rb_heap_t *heap = &heaps[i];
size_t pages_to_add = 0;
/*
* Step 1: Make sure every pool has the same number of pages, by adding empty pages
* to smaller pools. This is required to make sure the compact cursor can advance
* through all of the pools in `gc_sweep_compact` without hitting the "sweep &
* compact cursors met" condition on some pools before fully compacting others
*/
pages_to_add += max_existing_pages - heap->total_pages;
/*
* Step 2: Now add additional free pages to each size pool sufficient to hold all objects
* that want to be in that size pool, whether moved into it or moved within it
*/
objspace->heap_pages.allocatable_slots = desired_compaction.required_slots[i];
while (objspace->heap_pages.allocatable_slots > 0) {
heap_page_allocate_and_initialize(objspace, heap);
}
/*
* Step 3: Add two more pages so that the compact & sweep cursors will meet _after_ all objects
* have been moved, and not on the last iteration of the `gc_sweep_compact` loop
*/
pages_to_add += 2;
for (; pages_to_add > 0; pages_to_add--) {
heap_page_allocate_and_initialize_force(objspace, heap);
}
}
}
if (toward_empty) {
objspace->rcompactor.compare_func = compare_free_slots;
}
}
RB_GC_VM_UNLOCK(lev);
rb_gc_impl_start(rb_gc_get_objspace(), true, true, true, true);
rb_objspace_reachable_objects_from_root(root_obj_check_moved_i, objspace);
objspace_each_objects(objspace, heap_check_moved_i, objspace, TRUE);
objspace->rcompactor.compare_func = NULL;
return gc_compact_stats(self);
}
|
.verify_internal_consistency ⇒ nil
Verify internal consistency.
This method is implementation specific. Now this method checks generational consistency if RGenGC is supported.
9044 9045 9046 9047 9048 9049 |
# File 'ext/gc-4.0/gc/default/default.c', line 9044
static VALUE
gc_verify_internal_consistency_m(VALUE dummy)
{
rb_gc_verify_internal_consistency();
return Qnil;
}
|