модуль GC
Модуль GC предоставляет интерфейс к механизму сбора мусора Ruby «помечать и очищать».
Некоторые из базовых методов также доступны через модуль ObjectSpace.
Вы можете получить информацию об операциях модуля GC через GC::Profiler.
Константы
- INTERNAL_CONSTANTS
- OPTS
Открытые методы класса
static VALUE
rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
{
rb_objspace_t *objspace = &rb_objspace;
if (!stress_to_class) {
stress_to_class = rb_ary_tmp_new(argc);
}
rb_ary_cat(stress_to_class, argv, argc);
return self;
} 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;
} Отключает сбор мусора, возвращая true, если сбор мусора был уже отключён.
GC.disable #=> false GC.disable #=> true
VALUE
rb_gc_enable(void)
{
rb_objspace_t *objspace = &rb_objspace;
int old = dont_gc;
dont_gc = FALSE;
return old ? Qtrue : Qfalse;
} Включает сбор мусора, возвращая true, если сбор мусора был ранее отключён.
GC.disable #=> false GC.enable #=> true GC.enable #=> false
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);
} Возвращает информацию о последнем сборе мусора.
static VALUE
gc_malloc_allocated_size(VALUE self)
{
return UINT2NUM(rb_objspace.malloc_params.allocated_size);
} Возвращает размер памяти, выделенной функцией malloc().
Доступно только, если ruby был скомпилирован с CALC_EXACT_MALLOC_SIZE.
static VALUE
gc_malloc_allocations(VALUE self)
{
return UINT2NUM(rb_objspace.malloc_params.allocations);
} Возвращает количество выделений памяти функцией malloc().
Доступно только, если ruby был скомпилирован с CALC_EXACT_MALLOC_SIZE.
static VALUE
rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
{
rb_objspace_t *objspace = &rb_objspace;
int i;
if (stress_to_class) {
for (i = 0; i < argc; ++i) {
rb_ary_delete_same(stress_to_class, argv[i]);
}
if (RARRAY_LEN(stress_to_class) == 0) {
stress_to_class = 0;
}
}
return Qnil;
} 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);
gc_finalize_deferred(objspace);
return Qnil;
} Инициирует сбор мусора, если он не отключен вручную.
Этот метод определён со ключевыми аргументами, которые по умолчанию равны true:
def GC.start(full_mark: true, immediate_sweep: true); end
Используйте full_mark: false для выполнения небольшого сбора GC. Используйте immediate_sweep: false для отсрочки очистки (используйте ленивую очистку).
Примечание: Эти ключевые аргументы зависят от реализации и версии. Они не гарантируют совместимость в будущем и могут быть проигнорированы, если базовая реализация их не поддерживает.
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;
} Возвращает словарь с информацией о GC.
Словарь включает информацию о внутренней статистике GC, такой как:
{
: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_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
}
Содержание словаря зависит от реализации и может быть изменено в будущем.
Этот метод ожидается только для работы с C Ruby.
static VALUE
gc_stress_get(VALUE self)
{
rb_objspace_t *objspace = &rb_objspace;
return ruby_gc_stress_mode;
} Возвращает текущий статус режима стресса GC.
static VALUE
gc_stress_set_m(VALUE self, VALUE flag)
{
rb_objspace_t *objspace = &rb_objspace;
gc_stress_set(objspace, flag);
return flag;
} Обновляет режим стресса GC.
Когда режим стресса включён, GC вызывается при каждой возможности сбора мусора: все выделения памяти и объектов.
Включение режима стресса ухудшит производительность, он предназначен только для отладки.
Флаг может быть true, false или целое число, полученное в результате побитового ИЛИ с последующими флагами.
0x01:: no major GC 0x02:: no immediate sweep 0x04:: full mark after malloc/calloc/realloc
static VALUE
gc_verify_internal_consistency(VALUE dummy)
{
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 number: 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 number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.old_objects, data.old_object_count);
}
if (objspace->rgengc.uncollectible_wb_unprotected_objects != data.remembered_shady_count) {
rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.uncollectible_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;
} Проверка внутренней согласованности.
Этот метод зависит от реализации. Сейчас этот метод проверяет генерационную согласованность, если поддерживается RGenGC.
Открытые методы экземпляра
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);
gc_finalize_deferred(objspace);
return Qnil;
} Инициирует сбор мусора, если он не отключен вручную.
Этот метод определён со ключевыми аргументами, которые по умолчанию равны true:
def GC.start(full_mark: true, immediate_sweep: true); end
Используйте full_mark: false для выполнения небольшого сбора GC. Используйте immediate_sweep: false для отсрочки очистки (используйте ленивую очистку).
Примечание: Эти ключевые аргументы зависят от реализации и версии. Они не гарантируют совместимость в будущем и могут быть проигнорированы, если базовая реализация их не поддерживает.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.