Garbage collection no Ruby

Post on 27-Jun-2015

86 views 0 download

Tags:

description

Talk no TDC Florianópolis 2014

Transcript of Garbage collection no Ruby

Garbage Collection Ruby

Gerenciamento manual de memória

Objeto 01 Objeto 02

Desalocar manualmente

Objeto 01 Objeto 02

Objeto 01

Mas imagine o seguinte cenário

Objeto 01 Objeto 02

Objeto 01 Objeto 02

Referência para um objeto que não existe mais

Seu sistema pode quebrar

Ou pior…

Ele pode gerar resultados incorretos

Outras preocupações além do domínio da aplicação

Entender como os módulos que você utiliza gerenciam sua memória

Lauro Caetano @laurocaetano

Open Source

Rails

Rails core team

O que é Garbage Collection e como ele foi evoluindo a cada nova versão do Ruby

Agenda• O que é Garbage Collection

• Garbage Collection no Ruby - Mark and sweep

• Desvantagens do Mark and Sweep

• Evolução

• Lazy Sweep - Ruby 1.9

• Bitmap Mark - Ruby 2.0

• Generational Garbage Collection - Ruby 2.1

O que é Garbage Collection?

Gerenciamento dinâmico automático de memória

3 Responsabilidades

1. Alocar espaço para novos objetos

2. Identificar os objetos ainda vivos

3. Recuperar o espaço ocupado por objetos

mortos

Garbage Collection no Ruby

Ruby ainda utiliza o mesmo algoritmo que foi inventado a mais

de 50 anos por John MacCarthy

Mark-Sweep

Free List

Hora de limpar o Heap

Stop the world

Percorre todos os objetos do heap e marca os que

ainda estão vivos

Varre novamente o heap, mas agora em busca dos objetos não marcados e os remove do heap

Volta a executar o seu programa

Vamos ao código

!

1 def new! 2 ref = allocate! 3 ! 4 if ref.nil?! 5 collect! 6 ! 7 if ref.nil?! 8 raise "Out of memory"! 9 end!10 end!11 end!!!

12 !13 def collect!14 mark_from_roots!15 sweep(@heap_start, @heap_end)!16 end!17 !!!

17 !18 def mark_from_roots!19 initialize(worklist)!20 !21 @roots.each do |fld|!22 ref = fld!23 if !ref.nil? && !marked?(ref)!24 set_marked(ref)!25 mark!26 end!27 end!28 end!29

!

32 !33 def mark!34 while(@worklist.any?)!35 ref = remove(worklist)!36 !37 pointers(ref).each do |fld|!38 child = fld!39 !40 if !child.nil? && !marked?(child)!41 set_marked(child)!42 add(@worklist, child)!43 end!44 end!45 end!46 end!47

47 !48 def sweep(heap_start, heap_end)!49 scan = start!50 !51 while (scan < heap_end)!52 if marked?(scan)!53 unset_marked(scan)!54 else!55 free(scan)!56 end!57 !58 scan = next_object(scan)!59 end!60 end

Desvantagens do Mark and sweep

Fazer Full GC toda hora que o heap está cheio não

parece uma boa ideia

Stop the world

Mark and sweep é proporcional ao tamanho

do heap

Evolução

Lazy Sweep Ruby 1.9

Fazer Full GC toda hora que o heap está cheio não

parece uma boa ideia

Recuperar apenas o espaço necessário para criar um novo

objeto e permitir que a aplicação continue rodando

Agora o sweep não para mais o mundo todo

A alocação é responsável por checar se existe

espaço disponível

Caso não tenha espaço disponível, fazer Lazy Sweep

até obter o espaço necessário

12 !13 def allocate(size)!14 result = remove(size)!15 !16 if result.nil?!17 lazy_sweep(size)!18 result = remove(size)!19 end!20 !21 result!22 end!23

Bitmap Mark Ruby 2.0

Como os bits de marcação no ficavam objeto, os valores

eram sempre diferentes

Para possibilitar que o Unix compartilhe valores iguais

Os bits de marcação foram movidos para uma

tabela de bitmap

1 1 1 1 10 0

Generational Garbage Collection Ruby 2.1

Mark and sweep é proporcional ao tamanho

do heap

Weak generational hypothesis

O coletor processa mais frequentemente objetos novos do que objetos

maduros

Um objeto maduro é aquele que permanece ativo por

um algum período de tempo

Enquanto um objeto novo é aquele que seu sistema

acabou de criar

Geração Nova Geração Madura

Quando o mark and sweep terminar, os objetos restantes serão considerados maduros

Geração Nova Geração Madura

Geração Nova Geração Madura

Objetos maduros não serão marcados novamente

até um próximo full GC

Quando o full GC ocorrer, todos os objetos passarão

pelo mark and sweep

É legal entender como as coisas funcionam

Obrigado@laurocaetano

github.com/laurocaetano

Bonus

JRuby and Rubinius.

Copying Garbage Collection

Segmento de memória contínua

Bump Allocation

Aloca segmentos adjacentes de memória, mantendo um ponteiro

para a próxima alocação

Próxima alocação

Próxima alocação

Próxima alocação

Objetos podem ser de tamanhos diferentes

A grande vantagem é que valores relacionados ficam

próximos

A CPU pode cachear a região de memória que for acessada frequentemente

Também utiliza o Garbage Collection Generacional

Ruby 2.2

GC Simbolos

https://bugs.ruby-lang.org/issues/9634

Obrigado@laurocaetano

github.com/laurocaetano