Ruby/GC
توفر الوحدة GC واجهة لتحديد ومسح آلية جمع البيانات المهملة في روبي.
تتوفر أيضًا بعض التوابع الأساسية من خلال الوحدة ObjectSpace.
ويمكن الحصول على المزيد من المعلومات حول تشغيل GC من خلال GC::Profiler.
الثوابت
INTERNAL_CONSTANTS
OPTS
توابع الصنف العام
add_stress_to_class(*args)
أمثلة
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;
}
count → Integer
عدد مرات حدوث GC.
إعادة عدد مرات حدوث GC منذ بدء العملية.
أمثلة
static VALUE
gc_count(VALUE self)
{
return SIZET2NUM(rb_gc_count());
}
disable → true or false
تعطيل جمع البيانات المهملة، وإعادة true
إذا كان جمع البيانات المهملة مُعطَّلًا بالفعل.
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;
}
zero? → true أو false
تفعيل جمع البيانات المهملة، وإعادة true
إذا كان جمع البيانات المهملة مُعطَّلًا بالفعل.
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;
}
latest_gc_info → {:gc_by=>:newobj}
latest_gc_info(hash) → hash
latest_gc_info(:major_by) → :malloc
إعادة معلومات حول أحدث عملية جمع البيانات المهملة.
أمثلة
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);
}
malloc_allocated_size → Integer
إعادة حجم الذاكرة المخصصة من قِبَل malloc()
.
ويتوفر فقط إذا بُنيت روبي مع CALC_EXACT_MALLOC_SIZE
.
أمثلة
static VALUE
gc_malloc_allocated_size(VALUE self)
{
return UINT2NUM(rb_objspace.malloc_params.allocated_size);
}
malloc_allocations → Integer
إعادة عدد عمليات مُخصصات malloc()
.
ويتوفر فقط إذا بُنيت روبي مع CALC_EXACT_MALLOC_SIZE
.
أمثلة
static VALUE
gc_malloc_allocations(VALUE self)
{
return UINT2NUM(rb_objspace.malloc_params.allocations);
}
remove_stress_to_class(*args)
أمثلة
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;
}
start → nil
start(full_mark: true, immediate_sweep: true) → nil
بدء تجميع البيانات المهملة، ما لم تُعطَّل يدويًا.
يُحدد هذا التابع بوسائط الكلمات المفتاحية قِيَمَها الافتراضية true
:
def GC.start(full_mark: true, immediate_sweep: true); end
يُضبط full_mark
بالقيمة false
لتنفيذ GC ثانوية. يُضبط immediate_sweep
بالقيمة false
لتأجيل المسح (استخدام المسح البطيء).
ملاحظة: تعتمد وسائط الكلمات المفتاحية هذه على التطبيق والإصدار. وليس من المضمون أن تظل متوافقة في المستقبل، ويمكن تجاهلها إذا كان التطبيق الأساسي لا يدعمها.
أمثلة
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;
}
stat → Hash
stat(hash) → hash
stat(:key) → Numeric
إعادة تجزئة Hash تحتوي على معلومات حول 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.
أمثلة
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;
}
stress → integer, true or false
إعادة الحالة الحالية لوضع الضغط لـ GC.
أمثلة
static VALUE
gc_stress_get(VALUE self)
{
rb_objspace_t *objspace = &rb_objspace;
return ruby_gc_stress_mode;
}
stress = flag → flag
تحديث وضع الضغط لـ GC.
عند تفعيل وضع الضغط، يُستدعى GC في كل فرصة GC: كافة عمليات تخصيص الذاكرة والكائنات.
سيؤدي تفعيل وضع الضغط إلى خفض الأداء، ويُستعمل فقط للتنقيح.
يمكن أن تكون الراية true
، أو false
، أو عدد صحيح مُجرى على بِتاته العامل OR تبعًا للرايات.
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;
gc_stress_set(objspace, flag);
return flag;
}
verify_internal_consistency → nil
التحقق من الاتساق الداخلي.
هذا التابع خاص بالتطبيق. يتحقق هذا التابع الآن من تناسق الأجيال إذا كان RGenGC
مدعومًا.
أمثلة
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;
}
توابع المثيل العام
garbage_collect → nil
GC; garbage_collect → nil
garbage_collect(full_mark: true, immediate_sweep: true) → nil
بدء تجميع البيانات المهملة، ما لم تُعطَّل يدويًا.
يُحدد هذا التابع بوسائط الكلمات المفتاحية قِيَمَها الافتراضية true
:
def GC.start(full_mark: true, immediate_sweep: true); end
يُضبط full_mark
بالقيمة false
لتنفيذ GC ثانوية. ,يُضبط immediate_sweep
بالقيمة false
لتأجيل المسح (استخدام المسح البطيء).
ملاحظة: تعتمد وسائط الكلمات المفتاحية هذه على التطبيق والإصدار. وليس من المضمون أن تكون متوافقة في المستقبل، ويمكن تجاهلها إذا كان التطبيق الأساسي لا يدعمها.
أمثلة
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;
}