ruby & gcs (qconsp 2014)

99
Ruby & GCs Entendendo Gerenciamento de Memória

Upload: fabio-akita

Post on 10-May-2015

2.507 views

Category:

Technology


2 download

DESCRIPTION

Gerenciamento de Memória não é um problema resolvido. Estamos constantemente evoluindo formas de trabalhar memória em diferentes cenários. Garbage Collectors não são mágicos, são um conjunto de trade-offs entre performance e uso de memória e esta palestra vai desmistificar muitos desses conceitos que são válidos para Ruby mas também para Java e outras VMs.

TRANSCRIPT

Page 1: Ruby & GCs (QConSP 2014)

Ruby & GCsEntendendo Gerenciamento de Memória

Page 2: Ruby & GCs (QConSP 2014)
Page 3: Ruby & GCs (QConSP 2014)
Page 4: Ruby & GCs (QConSP 2014)

"G1 GC is an incremental parallel compacting GC that provides more predictable pause times compared to CMS GC and Parallel Old GC. By

introducing a parallel, concurrent and multi-phased marking cycle, G1 GC can work with

much larger heaps while providing reasonable worst-case pause times."

Page 5: Ruby & GCs (QConSP 2014)
Page 6: Ruby & GCs (QConSP 2014)
Page 7: Ruby & GCs (QConSP 2014)

Obsoletos Atuais

1.8.6 1.9.3

1.8.7 2.0.0

1.9.2 2.1.1

Page 8: Ruby & GCs (QConSP 2014)

#include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memory\n"); return 1; } ! *ptr_one = 25; printf("%d\n", *ptr_one); ! free(ptr_one); ! return 0; }

Page 9: Ruby & GCs (QConSP 2014)

#include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memory\n"); return 1; } ! *ptr_one = 25; printf("%d\n", *ptr_one); ! free(ptr_one); ! return 0; }

Page 10: Ruby & GCs (QConSP 2014)

#include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memory\n"); return 1; } ! *ptr_one = 25; printf("%d\n", *ptr_one); ! free(ptr_one); ! return 0; }

Page 11: Ruby & GCs (QConSP 2014)

#include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memory\n"); return 1; } ! *ptr_one = 25; printf("%d\n", *ptr_one); ! free(ptr_one); ! return 0; }

0000 0000

0000 0000

0000 0000

0001 1001

Page 12: Ruby & GCs (QConSP 2014)

#include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memory\n"); return 1; } ! *ptr_one = 25; printf("%d\n", *ptr_one); ! free(ptr_one); ! return 0; }

0000 0000

0000 0000

0000 0000

0001 1001

Page 13: Ruby & GCs (QConSP 2014)

40 bytes livres

Page 14: Ruby & GCs (QConSP 2014)

Slot (40 bytes)

Heap (ex 6 slots)

Page 15: Ruby & GCs (QConSP 2014)

Slot (40 bytes)

Heap (ex 6 slots)

Instância de RVALUE

Page 16: Ruby & GCs (QConSP 2014)

typedef 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 RFloat flonum; struct RString string; struct RArray array; struct RRegexp regexp; struct RHash hash; struct RData data; struct RTypedData typeddata; struct RStruct rstruct; struct RBignum bignum; struct RFile file; struct RNode node; struct RMatch match; struct RRational rational; struct RComplex complex; struct { struct RBasic basic; VALUE v1; VALUE v2; VALUE v3; } values; } as; #if GC_DEBUG const char *file; VALUE line; #endif } RVALUE;

RVALUE

struct 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; };

RSTRING(str)->as.heap.ptr

Page 17: Ruby & GCs (QConSP 2014)

Slot (40 kb)

Heap (ex 6 slots)

Instância de RVALUE

Dados do RVALUE

Page 18: Ruby & GCs (QConSP 2014)
Page 19: Ruby & GCs (QConSP 2014)

Slot (40 kb)

Heap (ex 6 slots)

Instância de RVALUE

Dados do RVALUE

Page 20: Ruby & GCs (QConSP 2014)

Slot (40 kb)

Heap (ex 6 slots)

Instância de RVALUE

Dados do RVALUE

Page 21: Ruby & GCs (QConSP 2014)

Mark and Sweep GC

Full Marking and Full Sweep GC

Page 22: Ruby & GCs (QConSP 2014)

• Slots de mesmo tamanho (não há problema com fragmentação)

• Quanto mais heaps, mais lento

• Fase de marcação conservadora

• pode haver “leaks” (ex. constantes)

• Processo “Stop-the-World"

Page 23: Ruby & GCs (QConSP 2014)
Page 24: Ruby & GCs (QConSP 2014)
Page 25: Ruby & GCs (QConSP 2014)

Master Unicorn ou Passenger

Rails App

NGINX

Rails App

Rails App

fork() fork()

request

150mb 150mb 150mb

Page 26: Ruby & GCs (QConSP 2014)
Page 27: Ruby & GCs (QConSP 2014)

Copy on Write (CoW)

só copia o trecho da memória quando for modificada

Page 28: Ruby & GCs (QConSP 2014)
Page 29: Ruby & GCs (QConSP 2014)

“Mark Bit Map”

Page 30: Ruby & GCs (QConSP 2014)

Bitmap Marking GC

Full Bitmap Marking and Full Sweep GC

Page 31: Ruby & GCs (QConSP 2014)

Master Unicorn ou Passenger

Rails App

NGINX

Rails App

Rails App

fork() fork()

request

150mb 100mb 100mb

Page 32: Ruby & GCs (QConSP 2014)

Mark Sweep Mark Sweep Mark Sweep

Page 33: Ruby & GCs (QConSP 2014)

Mark Mark Mark

Page 34: Ruby & GCs (QConSP 2014)

Lazy Sweep GC

Full Bitmap Marking and Lazy Sweep GC

Page 35: Ruby & GCs (QConSP 2014)
Page 36: Ruby & GCs (QConSP 2014)

https://gist.github.com/akitaonrails/10212233

Page 37: Ruby & GCs (QConSP 2014)

http://u.akita.ws/samsaffron_ruby20

Page 38: Ruby & GCs (QConSP 2014)
Page 39: Ruby & GCs (QConSP 2014)

RUBY_GC_MALLOC_LIMIT=30000000 \

RUBY_HEAP_MIN_SLOTS=800000 \

bundle exec rails server

Page 40: Ruby & GCs (QConSP 2014)

RUBY_GC_MALLOC_LIMIT 8.000.000 30.000.000

RUBY_HEAP_MIN_SLOTS 10.000 800.000

Page 41: Ruby & GCs (QConSP 2014)
Page 42: Ruby & GCs (QConSP 2014)

env_gc_malloc_limit_in_mb 7.6mb 26.6mb

total_gc_runs 105 65

heaps_with_used_slots 1.089 1.477

total_heaps_allocated 1.958 1.965

total_heaps_allocated_in_mb 30.6mb 30.7mb

heaps_to_allocate_next_gc 869 0

Page 43: Ruby & GCs (QConSP 2014)
Page 44: Ruby & GCs (QConSP 2014)

2.49Mb

71.9Mb

Page 45: Ruby & GCs (QConSP 2014)
Page 46: Ruby & GCs (QConSP 2014)
Page 47: Ruby & GCs (QConSP 2014)
Page 48: Ruby & GCs (QConSP 2014)
Page 49: Ruby & GCs (QConSP 2014)
Page 50: Ruby & GCs (QConSP 2014)
Page 51: Ruby & GCs (QConSP 2014)

GC Anterior

Page 52: Ruby & GCs (QConSP 2014)
Page 53: Ruby & GCs (QConSP 2014)
Page 54: Ruby & GCs (QConSP 2014)
Page 55: Ruby & GCs (QConSP 2014)
Page 56: Ruby & GCs (QConSP 2014)

Weak Generational Hypothesis

“Most young objects die young"

Page 57: Ruby & GCs (QConSP 2014)

Young Generation (Eden)

Old Generation (Tomb)

Page 58: Ruby & GCs (QConSP 2014)

Generational GC

Copying Garbage Collector

Page 59: Ruby & GCs (QConSP 2014)
Page 60: Ruby & GCs (QConSP 2014)
Page 61: Ruby & GCs (QConSP 2014)

From-Heap

To-Heap

Page 62: Ruby & GCs (QConSP 2014)

From-Heap

To-Heap

Page 63: Ruby & GCs (QConSP 2014)

Mark-Compact GC

Mark Copy Compact Heap Swap GC

Page 64: Ruby & GCs (QConSP 2014)

• “Stop-and-Copy”

• Sweep precisa ir slot a slot, neste é só considerar tudo no primeiro heap como livre

• Gerenciamento interno de ponteiros

• Feito para corrigir fragmentação

• Ruby tem slots de mesmo tamanho

• Não suporta Copy-on-Write

Page 65: Ruby & GCs (QConSP 2014)

Ruby 2.1.x

Shady vs Non-Shady

Page 66: Ruby & GCs (QConSP 2014)

Ruby Object

Write Barrier (Non-Shady only)

Ruby Array

Page 67: Ruby & GCs (QConSP 2014)

Shady Object

Non-Shady Object (Sunny)

Page 68: Ruby & GCs (QConSP 2014)

Mark bitmap (mark_bits[])

Shady bitmap ( rememberset_bits[])

Page 69: Ruby & GCs (QConSP 2014)

Objetos "Old" 96.4%

Objetos "Young" 3.6%

Objetos "Shady" 1.5%

Page 70: Ruby & GCs (QConSP 2014)

Mark Mark Mark

Page 71: Ruby & GCs (QConSP 2014)

Major GC

Minor GC

Page 72: Ruby & GCs (QConSP 2014)

2.49Mb

71.9Mb

Page 73: Ruby & GCs (QConSP 2014)
Page 74: Ruby & GCs (QConSP 2014)

Restricted Generational GC (RGenGC)

Full M&S for Shady, Generational for Non-Shady

Page 75: Ruby & GCs (QConSP 2014)

• Partial Markings, Lazy Sweeps = Menos Stop

• Shady objects não vão para o Tomb

• Write Barriers (referência old para new - non-Shady only)

• Compatível com extensões C (Shady)

• Objetos em Tomb só são remarcados em Full Mark

Page 76: Ruby & GCs (QConSP 2014)
Page 77: Ruby & GCs (QConSP 2014)
Page 78: Ruby & GCs (QConSP 2014)
Page 79: Ruby & GCs (QConSP 2014)
Page 80: Ruby & GCs (QConSP 2014)
Page 81: Ruby & GCs (QConSP 2014)
Page 82: Ruby & GCs (QConSP 2014)

http://u.akita.ws/samsaffron_ruby21

Page 83: Ruby & GCs (QConSP 2014)

ruby-trunk e ruby 2.1.2 (não lançado)

Page 84: Ruby & GCs (QConSP 2014)

http://u.akita.ws/samsaffron_ruby21

Page 85: Ruby & GCs (QConSP 2014)

< 1.3!(+ major GC)

Page 86: Ruby & GCs (QConSP 2014)

RUBY_GC_MALLOC_LIMIT_MAX=8000000 \

RUBY_GC_OLDMALLOC_LIMIT_MAX=8000000 \

RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=0.9

bundle exec rails server

força GC por diminuir o teto

basicamente desabilita minor GC

(de volta a Ruby 2.0.0)

Page 87: Ruby & GCs (QConSP 2014)

RUBY_GC_MALLOC_LIMIT_MAX 3210241024 8000000

RUBY_GC_OLDMALLOC_LIMIT_MAX 12810241024 8000000

RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0 0.9

RUBY_GC_HEAP_INIT_SLOTS 10000 300000

RUBY_GC_HEAP_FREE_SLOTS 4096 300000

RUBY_GC_HEAP_GROWTH_FACTOR 1.8 1.25

RUBY_GC_HEAP_GROWTH_MAX_SLOTS (no limit) 150000

(obs: monitore, mensure, tuning, mensure de novo!)

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

Page 88: Ruby & GCs (QConSP 2014)

• Objetos vão para Tomb se sobreviverem 1 GC

• Objetos podem ir para Tomb cedo demais

• Eden - Survivor - Tenured - Permanent

• RGENGC_THREEGEN mode (experimental)

• Parallel Marking (ex. em Thread separada)

• Tri-Color Marking (talvez)

• Futuro: Incremental Major Phase (major GC menores)

Page 89: Ruby & GCs (QConSP 2014)

Java• Young Generation

• -XX:+UseSerialGC (copying collector)

• -XX:+UseParallelGC (copying collector multi-thread)

• -XX:+UseParNewGC

• Old Generation

• -XX:+UseParallelOldGC

• -XX:+UseConcMarkSweepGC

Page 90: Ruby & GCs (QConSP 2014)

Master Unicorn ou Passenger

Rails App

NGINX

Rails App

Rails App

request

190ms 190ms 190ms

50ms de Full GC!

Page 91: Ruby & GCs (QConSP 2014)

Master Unicorn ou Passenger

Rails App

NGINX

Rails App

Rails App

request

140ms 140ms Full GC

Executa Full GC quando não receber request

Page 92: Ruby & GCs (QConSP 2014)

OOBGC

Out-of-Band Major GC

Page 93: Ruby & GCs (QConSP 2014)
Page 94: Ruby & GCs (QConSP 2014)
Page 95: Ruby & GCs (QConSP 2014)

Pausas foram de 125ms para 50ms

http://tmm1.net/ruby21-oobgc/

Page 96: Ruby & GCs (QConSP 2014)
Page 97: Ruby & GCs (QConSP 2014)
Page 98: Ruby & GCs (QConSP 2014)

http://u.akita.ws/rubymicroscope

Page 99: Ruby & GCs (QConSP 2014)

Obrigado!@akitaonrails

slideshare.net/akitaonrails www.akitaonrails.com