Top Banner
61

mri ruby GC

Apr 15, 2017

Download

Software

achempion
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: mri ruby GC
Page 2: mri ruby GC

Аудитория

Page 3: mri ruby GC

Руби освобождает страницы

Page 4: mri ruby GC

gc_sweep_finish(rb_objspace_t *objspace)

Page 5: mri ruby GC

heap_pages_free_unused_pages(rb_objspace_t *objspace)

Page 6: mri ruby GC

heap_page_free(rb_objspace_t *objspace, struct heap_page *page) { free(page); }

Page 7: mri ruby GC

О чем поговорим

• как работает GC

• как устроен GC

• планы ruby team

Page 8: mri ruby GC

gc.c

9381 lines and counting

Page 9: mri ruby GC

На первый взгляд

Page 10: mri ruby GC

Через пару дней

Page 11: mri ruby GC

Чем занимается• создает объекты

• выделяет память под них

• освобождает

• собирает статистику

• проверяет консистентность объектов

• …

• собирает мусор

Page 12: mri ruby GC

Структура

Page 13: mri ruby GC
Page 14: mri ruby GC

RVALUE

GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] # => 40

* sizeof(RVALUE) is

* 20 if 32-bit, double is 4-byte aligned

* 24 if 32-bit, double is 8-byte aligned

* 40 if 64-bit

Page 15: mri ruby GC

heap_page

GC::INTERNAL_CONSTANTS[:HEAP_OBJ_LIMIT] # => 408

HEAP_PAGE_OBJ_LIMIT = ((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)) / sizeof(struct RVALUE))

Page 16: mri ruby GC

RVALUEtypedef struct RVALUE { union { struct {

VALUE flags; /* always 0 for freed obj */ struct RVALUE *next; } free; struct RBasic basic; struct RObject object; struct RClass klass; struct RString string; ... struct RComplex complex; ... } as; } RVALUE;

Page 17: mri ruby GC

RStringstruct RString { struct RBasic basic; union {

struct { long len; char *ptr; union {

long capa; VALUE shared;

} aux; } heap; char ary[RSTRING_EMBED_LEN_MAX + 1];

} as; };

Page 18: mri ruby GC

Развитие

• early - Mark & Sweep

• 1.9.3 - Lazy Sweep

• 2.0 - CoW friendly

• 2.1 - Mark major / minor

• 2.2 - Inc major Mark, symbols

Page 19: mri ruby GC

Mark & Sweep

Page 20: mri ruby GC

Mark & Sweep

Page 21: mri ruby GC

Mark & SweepObjectSpace.reachable_objects_from_root.keys

[

[0] "vm",

[1] "machine_context",

[2] "global_list",

[3] "end_proc",

[4] "global_tbl"

]

Page 22: mri ruby GC

Mark & Sweep

Page 23: mri ruby GC

Mark & Sweep

Page 24: mri ruby GC

Mark & Sweep

> a = 'a' * 1024 * 1024 * 500

> a = nil; 4.times { GC.start }

Page 25: mri ruby GC

Mark & Sweep

Page 26: mri ruby GC

Markgc_mark_roots(rb_objspace_t *objspace, const char **categoryp) { rb_thread_t *th = GET_THREAD(); rb_vm_mark(th->vm); mark_tbl(objspace, finalizer_table); mark_current_machine_context(objspace, th); rb_gc_mark_encodings();

/* mark protected global variables */ rb_gc_mark_maybe(*list->varptr);

rb_mark_end_proc(); rb_gc_mark_global_tbl(); }

Page 27: mri ruby GC

Sweep

gc_sweep(rb_objspace_t *objspace) { if (immediate_sweep) { gc_sweep_start(objspace); gc_sweep_rest(objspace); } else { }

gc_heap_prepare_minimum_pages(objspace, heap_eden); }

Page 28: mri ruby GC
Page 29: mri ruby GC

Sweepgc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) { while (sweep_page) { heap->sweep_pages = next = sweep_page->next; gc_page_sweep(objspace, heap, sweep_page);

heap_unlink_page(objspace, heap, sweep_page); heap_add_page(objspace, heap_tomb, sweep_page);

sweep_page = next; }

if (heap->sweep_pages == NULL) { gc_sweep_finish(objspace); }

return heap->free_pages != NULL; }

Page 30: mri ruby GC
Page 31: mri ruby GC
Page 32: mri ruby GC

Lazy Sweep

Page 33: mri ruby GC

Lazy Sweep

gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap)

Page 34: mri ruby GC

Copy on Write (CoW)

Page 35: mri ruby GC
Page 36: mri ruby GC

heap_pagestruct heap_page {

struct heap_page *prev; short total_slots; short free_slots; short final_slots; struct heap_page *free_next; struct heap_page *next;

/* the following three bitmaps are cleared at the beginning of full GC */ bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT]; };

Page 37: mri ruby GC

RGenGC

Page 38: mri ruby GC

Major

Page 39: mri ruby GC

Minor

Page 40: mri ruby GC

Minor

Page 41: mri ruby GC

Minor

Page 42: mri ruby GC

4.times { GC.start }

Page 43: mri ruby GC

if (objspace->last_major_gc > 3 /* magic number */) { gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");

objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE; }

Major через каждые 3 Minor цикла

Page 44: mri ruby GC

RIncGC только для Major Mark

Page 45: mri ruby GC

RIncGC Major Mark

Page 46: mri ruby GC

RIncGC Major Mark

objspace->rincgc.step_slots = (objspace->marked_slots * 2) / ((objspace->rincgc.pooled_slots / HEAP_PAGE_OBJ_LIMIT) + 1);

Page 47: mri ruby GC

RIncGC Major Mark

Page 48: mri ruby GC

RIncGC Major Mark

heap_prepare(rb_objspace_t *objspace, rb_heap_t *heap)

Page 49: mri ruby GC

RGenGC RIncGC

Page 50: mri ruby GC

Restricted

Page 51: mri ruby GC

Много слайдов про remember set

Page 52: mri ruby GC

Много слайдов про write unprotected objects

Page 53: mri ruby GC

Немного слайдов про write protected objects

Page 54: mri ruby GC

Можно найти

• http://www.atdot.net/~ko1/activities/2015_rubyconfph_pub.pdf

• http://www.atdot.net/fp_store/f.p61can/file.data-incremental-gc.pdf

Page 55: mri ruby GC

Дополнительно

• http://tmm1.net/ruby21-rgengc/

• https://ruby-hacking-guide.github.io/gc.html

• Ruby Under a Microscope - Pat Shaughnessy

• http://engineering.heroku.com/blogs/2015-02-04-incremental-gc

Page 56: mri ruby GC

Дальнейшее развитие GC

Page 57: mri ruby GC
Page 58: mri ruby GC

ссылочка

https://esa-pages.io/p/sharing/2933/posts/5/2075ee3ce5a11a81cd00.html

Page 59: mri ruby GC
Page 60: mri ruby GC

Оптимизация Sweep

Page 61: mri ruby GC

Спасибо

achempion