Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby's GC RU

Ruby's GC RU

Доклад посвящен основным вехам в развитии сборщика мусора в Ruby. Также рассматриваются такие темы, как возможности настройки и профайлинга Ruby приложений, хранение объектов в Ruby и альтернативные подходы к реализации GC, реализованные в других языках программирования.

http://homeonrails.com/2012/11/rubys-gc-ru

D83b63db79b42978fe35e120550ca180?s=128

Anton Kaliaev

November 23, 2012
Tweet

Transcript

  1. None
  2. None
  3. None
  4. Original

  5. Mark Sweep Помечаются все живые объекты 1. Снимаются отметки с

    помеченных (живых) объектов 2. Память, хранящая мертвые объекты, освобождается
  6. Пример “b” – мертвый объект “a” – живой объект

  7. Ruby Heap [] [] “a” “b” Ruby Heap Slab Этот

    блок память очищается
  8. Общая структура Physical RAM Process Heap Process Heap Slab 1

    Process Heap Slab 2 rb_new_object malloc
  9. →Операция Mark & Sweep атомарная →Ваше ruby приложение блокируется на

    время работы сборщика мусора →GC работает на 1 ядре в 1 потоке
  10. Original Ruby 1.8

  11. new_heap_slab_size = previous_heap_slab_size * 1.8 Вместо попытки найти 1 смежный

    участок такого размера, разыскиваются несколько участков
  12. None
  13. Ruby хранит все ваши объекты в виде структур RValue Rstring

    Flags “a” 16 typedef struct RVALUE { 17 union { 18 #if 0 19 struct { 20 unsigned long flags; /* always 0 for freed obj */ 21 struct RVALUE *next; 22 } free; 23 #endif 24 struct RBasic basic; 25 struct RObject object; 26 struct RClass klass; 27 /*struct RFloat flonum;*/ 28 /*struct RString string;*/ 29 struct RArray array; 30 /*struct RRegexp regexp;*/ 31 struct RHash hash; 32 /*struct RData data;*/ 33 struct RStruct rstruct; 34 /*struct RBignum bignum;*/ 35 /*struct RFile file;*/ 36 } as; 37 } RVALUE;
  14. RBasic – базовый Ruby объект 00411 #define T_NONE RUBY_T_NONE 00412

    #define T_NIL RUBY_T_NIL 00413 #define T_OBJECT RUBY_T_OBJECT 00414 #define T_CLASS RUBY_T_CLASS 00415 #define T_ICLASS RUBY_T_ICLASS 00416 #define T_MODULE RUBY_T_MODULE 00417 #define T_FLOAT RUBY_T_FLOAT 00418 #define T_STRING RUBY_T_STRING 00419 #define T_REGEXP RUBY_T_REGEXP 00420 #define T_ARRAY RUBY_T_ARRAY 00421 #define T_HASH RUBY_T_HASH 00422 #define T_STRUCT RUBY_T_STRUCT 00423 #define T_BIGNUM RUBY_T_BIGNUM 00424 #define T_FILE RUBY_T_FILE 00425 #define T_FIXNUM RUBY_T_FIXNUM 00426 #define T_TRUE RUBY_T_TRUE 00427 #define T_FALSE RUBY_T_FALSE 00428 #define T_DATA RUBY_T_DATA 00429 #define T_MATCH RUBY_T_MATCH 00430 #define T_SYMBOL RUBY_T_SYMBOL 00431 #define T_RATIONAL RUBY_T_RATIONAL 00432 #define T_COMPLEX RUBY_T_COMPLEX 00433 #define T_UNDEF RUBY_T_UNDEF 00434 #define T_NODE RUBY_T_NODE 00435 #define T_ZOMBIE RUBY_T_ZOMBIE 00436 #define T_MASK RUBY_T_MASK →Flags содержит информацию о типе
  15. RString используется для строк 314 struct RString { 315 struct

    RBasic basic; 316 long len; 317 char *ptr; 318 union { 319 long capa; 320 VALUE shared; 321 } aux; 322 }; 1 a = 'hello' 2 b = a.dup 2 слота, ссылающихся на 1 адрес
  16. RNode используется для кода →Ruby код также хранится в куче

    →Это позволяет менять код во время исполнения (runtime) →Около 130 типов
  17. Ruby 1.8 Original Ruby 1.9

  18. Mark Sweep Помечаются все живые объекты 1. Проверяется, есть ли

    элемент во free list 2. Если есть, то используется он 3. Если нет, заново запускается mark
  19. Ruby Heap [] [] “a” “b” Ruby Heap Slab Rstring

    Flags “a” “b” Free list FL_MARK = M
  20. Когда требуется место для нового объекта, мы ищем его во

    free list. Если free list пустой и повторный mark не дал результатов, создается новая куча (ruby heap slab)
  21. None
  22. Original Ruby 1.8 Ruby 1.9 Ruby 2.0

  23. Ruby Heap header [] [] “a” “b” Ruby Heap Slab

    1 1 1 0 Bitmap
  24. Original Ruby 1.8 Ruby 1.9 Ruby 2.0 Future?

  25. Разбиение на ветки

  26. →Каждому воркеру отдается одна ветка →Воркер может брать задачи у

    другого воркера (task stealing)
  27. None
  28. →RUBY_GC_MALLOC_LIMIT →RUBY_HEAP_MIN_SLOTS →RUBY_HEAP_SLOTS_GROWTH_FACTOR →RUBY_HEAP_SLOTS_INCREMENT →RUBY_HEAP_FREE_MIN Для MRI Ruby нужен патч,

    чтобы иметь возможность тюнить GC
  29. RUBY_GC_MALLOC_LIMIT void * ruby_xmalloc(size) long size; { voide *mem; if

    (malloced > malloc_limit) garbage_collect(); mem = malloc(size); malloced += size; return mem; } →При достижении предела запускается GC →По умолчанию - 8MB →Сервера могут выбирать больше 8MB за 1 запрос
  30. RUBY_HEAP_MIN_SLOTS →По умолчанию – 10000 →Количество слотов в первой куче

    (slab) →Базовое rails приложение запускается с почти 500000 объектами в куче
  31. RUBY_HEAP_SLOTS_GROWTH_FACTOR →По умолчанию – 1.8 →Пример роста: • 10000 •

    10000 + 18001 = 28001 • 10000 + 18001 + 36001 = 64002
  32. RUBY_HEAP_SLOTS_INCREMENT →Приращение количества слотов →По умолчанию – 1 RUBY_HEAP_FREE_MIN →Если

    после запуска GC количество слотов меньше данного значения, создается еще 1 куча (slab) →По умолчанию – 4096
  33. None
  34. →ObjectSpace.count_objects →perftools.rb →ruby-prof →memprof →gdb.rb

  35. None
  36. →tri-color →copying →generational →reference- counting (python/perl/php) →explicit (malloc/free)

  37. None
  38. None
  39. →RNode объекты помещаются в специальные heap slabs, так что они

    не сканируются каждый раз при проходе GC →играет большую роль так как код занимает большую часть кучи
  40. None