Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Ruby & GCs (QConSP 2014)

3,153 views

Published on

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.

Published in: Technology
  • Be the first to comment

Ruby & GCs (QConSP 2014)

  1. 1. Ruby & GCs Entendendo Gerenciamento de Memória
  2. 2. "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."
  3. 3. Obsoletos Atuais 1.8.6 1.9.3 1.8.7 2.0.0 1.9.2 2.1.1
  4. 4. #include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memoryn"); return 1; } ! *ptr_one = 25; printf("%dn", *ptr_one); ! free(ptr_one); ! return 0; }
  5. 5. #include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memoryn"); return 1; } ! *ptr_one = 25; printf("%dn", *ptr_one); ! free(ptr_one); ! return 0; }
  6. 6. #include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memoryn"); return 1; } ! *ptr_one = 25; printf("%dn", *ptr_one); ! free(ptr_one); ! return 0; }
  7. 7. #include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memoryn"); return 1; } ! *ptr_one = 25; printf("%dn", *ptr_one); ! free(ptr_one); ! return 0; } 0000 0000 0000 0000 0000 0000 0001 1001
  8. 8. #include<stdio.h> int main() { int *ptr_one; ! ptr_one = (int *)malloc(sizeof(int)); ! if (ptr_one == 0) { printf("ERROR: Out of memoryn"); return 1; } ! *ptr_one = 25; printf("%dn", *ptr_one); ! free(ptr_one); ! return 0; } 0000 0000 0000 0000 0000 0000 0001 1001
  9. 9. 40 bytes livres
  10. 10. Slot (40 bytes) Heap (ex 6 slots)
  11. 11. Slot (40 bytes) Heap (ex 6 slots) Instância de RVALUE
  12. 12. 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
  13. 13. Slot (40 kb) Heap (ex 6 slots) Instância de RVALUE Dados do RVALUE
  14. 14. Slot (40 kb) Heap (ex 6 slots) Instância de RVALUE Dados do RVALUE
  15. 15. Slot (40 kb) Heap (ex 6 slots) Instância de RVALUE Dados do RVALUE
  16. 16. Mark and Sweep GC Full Marking and Full Sweep GC
  17. 17. • 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"
  18. 18. Master Unicorn ou Passenger Rails App NGINX Rails App Rails App fork() fork() request 150mb 150mb 150mb
  19. 19. Copy on Write (CoW) só copia o trecho da memória quando for modificada
  20. 20. “Mark Bit Map”
  21. 21. Bitmap Marking GC Full Bitmap Marking and Full Sweep GC
  22. 22. Master Unicorn ou Passenger Rails App NGINX Rails App Rails App fork() fork() request 150mb 100mb 100mb
  23. 23. Mark Sweep Mark Sweep Mark Sweep
  24. 24. Mark Mark Mark
  25. 25. Lazy Sweep GC Full Bitmap Marking and Lazy Sweep GC
  26. 26. https://gist.github.com/akitaonrails/10212233
  27. 27. http://u.akita.ws/samsaffron_ruby20
  28. 28. RUBY_GC_MALLOC_LIMIT=30000000 RUBY_HEAP_MIN_SLOTS=800000 bundle exec rails server
  29. 29. RUBY_GC_MALLOC_LIMIT 8.000.000 30.000.000 RUBY_HEAP_MIN_SLOTS 10.000 800.000
  30. 30. 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
  31. 31. 2.49Mb 71.9Mb
  32. 32. GC Anterior
  33. 33. Weak Generational Hypothesis “Most young objects die young"
  34. 34. Young Generation (Eden) Old Generation (Tomb)
  35. 35. Generational GC Copying Garbage Collector
  36. 36. From-Heap To-Heap
  37. 37. From-Heap To-Heap
  38. 38. Mark-Compact GC Mark Copy Compact Heap Swap GC
  39. 39. • “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
  40. 40. Ruby 2.1.x Shady vs Non-Shady
  41. 41. Ruby Object Write Barrier (Non-Shady only) Ruby Array
  42. 42. Shady Object Non-Shady Object (Sunny)
  43. 43. Mark bitmap (mark_bits[]) Shady bitmap (rememberset_bits[])
  44. 44. Objetos "Old" 96.4% Objetos "Young" 3.6% Objetos "Shady" 1.5%
  45. 45. Mark Mark Mark
  46. 46. Major GC Minor GC
  47. 47. 2.49Mb 71.9Mb
  48. 48. Restricted Generational GC (RGenGC) Full M&S for Shady, Generational for Non-Shady
  49. 49. • 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
  50. 50. http://u.akita.ws/samsaffron_ruby21
  51. 51. ruby-trunk e ruby 2.1.2 (não lançado)
  52. 52. http://u.akita.ws/samsaffron_ruby21
  53. 53. < 1.3! (+ major GC)
  54. 54. 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)
  55. 55. 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/
  56. 56. • 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)
  57. 57. Java • Young Generation • -XX:+UseSerialGC (copying collector) • -XX:+UseParallelGC (copying collector multi-thread) • -XX:+UseParNewGC • Old Generation • -XX:+UseParallelOldGC • -XX:+UseConcMarkSweepGC
  58. 58. Master Unicorn ou Passenger Rails App NGINX Rails App Rails App request 190ms 190ms 190ms 50ms de Full GC!
  59. 59. Master Unicorn ou Passenger Rails App NGINX Rails App Rails App request 140ms 140ms Full GC Executa Full GC quando não receber request
  60. 60. OOBGC Out-of-Band Major GC
  61. 61. Pausas foram de 125ms para 50ms http://tmm1.net/ruby21-oobgc/
  62. 62. http://u.akita.ws/rubymicroscope
  63. 63. Obrigado! @akitaonrails slideshare.net/akitaonrails www.akitaonrails.com

×