O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

TDC2016POA | Trilha Ruby - Stack Level too Deep e Tail Call Optimization: É uma boa ideia fazer recursão em Ruby?

178 visualizações

Publicada em

Stack Level too Deep e Tail Call Optimization: É uma boa ideia fazer recursão em Ruby?

Publicada em: Educação
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

TDC2016POA | Trilha Ruby - Stack Level too Deep e Tail Call Optimization: É uma boa ideia fazer recursão em Ruby?

  1. 1. Globalcode – Open4education Trilha – Ruby Guilherme Baptista
  2. 2. Globalcode – Open4education 10 anos deixando linhas de código por aí em lugares como:
  3. 3. Globalcode – Open4education Stack Level too Deep Tail Call Optimization É uma boa ideia fazer recursão em Ruby?
  4. 4. Familiar ? file.rb:10:in `call': stack level too deep (SystemStackError) from file.rb:10:in `<main>'
  5. 5. Qual o significado?file.rb:10:in `call': stack level too deep (SystemStackError) from file.rb:10:in `<main>'
  6. 6. Qual o significado?file.rb:10:in `call': stack level too deep (SystemStackError) from file.rb:10:in `<main>'
  7. 7. stack overflow? file.rb:10:in `call': stack level too deep (SystemStackError) from file.rb:10:in `<main>'
  8. 8. stack overflow?
  9. 9. ?
  10. 10. file.rb:10:in `call': stack level too deep (SystemStackError) from file.rb:10:in `<main>' O que é?
  11. 11. É uma “proteção” contra loops infinitos?
  12. 12. É uma “proteção” contra loops infinitos?
  13. 13. É uma “proteção” contra loops infinitos?
  14. 14. É uma “proteção” contra loops infinitos?
  15. 15. É uma “proteção” contra loops infinitos?
  16. 16. É um erro causado por uso de memória em excesso?
  17. 17. É um erro causado por uso de memória em excesso?
  18. 18. É um erro causado por uso de memória em excesso?
  19. 19. É um erro causado por uso de memória em excesso? file.rb:8:in `<main>': failed to allocate memory (NoMemoryError)
  20. 20. Bônus: Uma linha para acabar com a memória RAM em segundos: Obs.: Não rodar no irb do seu servidor em produção... #fikdik
  21. 21. É uma “proteção” para não deixar um método chamar a si mesmo?
  22. 22. É uma “proteção” para não deixar um método chamar a si mesmo?
  23. 23. É uma “proteção” para não deixar um método chamar a si mesmo? Done !
  24. 24. É uma “proteção” para não deixar um método chamar a si mesmo muitas vezes?
  25. 25. É uma “proteção” para não deixar um método chamar a si mesmo muitas vezes?
  26. 26. É uma “proteção” para não deixar um método chamar a si mesmo muitas vezes? Done !
  27. 27. É uma “proteção” para não deixar um método chamar a si mesmo infinitamente?
  28. 28. É uma “proteção” para não deixar um método chamar a si mesmo infinitamente? file.rb:2:in `me_myself_and_i': stack level too deep (SystemStackError) from file.rb:2:in `me_myself_and_i' from file.rb:2:in `me_myself_and_i' from file.rb:2:in `me_myself_and_i' from file.rb:2:in `me_myself_and_i' ... 11901 levels... from file.rb:2:in
  29. 29. Será?
  30. 30. 5
  31. 31. 1 + 1 + 1 + 1 + 1
  32. 32. 5
  33. 33. 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +
  34. 34. 2000 0
  35. 35. 2000 0
  36. 36. file.rb:7:in `eval': stack level too deep (SystemStackError) from file.rb:7:in `<main>'
  37. 37. É uma “proteção” para não deixar um método chamar a si mesmo infinitamente? file.rb:7:in `eval': stack level too deep (SystemStackError) from file.rb:7:in `<main>'
  38. 38. Pode não ser bem isso...
  39. 39. Vamos falar sobre pilha:
  40. 40. Stack (abstract data type) LIFO: last-in, first-out (o último que entra é o primeiro que sai)
  41. 41. Stack (LIFO: last-in, first-out) Stac k
  42. 42. Stack (LIFO: last-in, first-out)
  43. 43. Stack (LIFO: last-in, first-out)
  44. 44. Stack (LIFO: last-in, first-out)
  45. 45. Stack (LIFO: last-in, first-out)
  46. 46. Stack (LIFO: last-in, first-out)
  47. 47. Stack (LIFO: last-in, first-out)
  48. 48. Stack (LIFO: last-in, first-out)
  49. 49. Em Ruby tudo é objeto.
  50. 50. RubyVM::InstructionSequence
  51. 51. RubyVM::InstructionSequence.of Proc Ou method Ruby Code down to VM Instructions
  52. 52. YARBx02x00x00x00x03x00x00x00rx02x00x00x00x00x00x00x01x00 x00x00x02x00x00x00x04x00x00x00xF9x01x00x00xFDx01x00x00bx 02x00x00x86_64- linuxx00*x00x00x00x00x00x00x00bx00x00x00x00x00x00x00*x00 x00x00x00x00x00x00x01x00x00x00x00x00x00x00Zx00x00x00x00x 00x00x00Zx00x00x00x00x00x00x00;x00x00x00x00x00x00x00x00x 00x00x00x00x00x00x00x00x00x00x00x00x00x00x00Zx00x00x00x0 0x00x00x00;x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00Zx00x00x00x00x00x00x00;x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x 00x00*x00x00x00x00x00x00x00x10x00x00x00x00x00x00x001x00x 00x00x00x00x00x00x00x00x00x00vx00x00x00x02x00x00x00rx00 x00x00x11x00x00x00x0Fx00x00x00x13x00x00x00rx00x00x00x01 x00x00x00x00x00x00x00x10x00x00x00x01x00x00x00x01x00x00x 00x00x00x00x00x10x00x00x00x01x00x00x00x01x00x00x00x00x00 x00x00x10x00x00x00x01x00x00x00x01x00x00x00x02x00x00x00x 01x00x00x00x14x00x00x009x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x01x00x00x00x00x00x00x00x01x00x00 x00x00x00x00x00x02x00x00x00x00x00x00x00x02x00x00x00x00x0 0x00x00x17x00x00x00x00x00x00x00xD9x00x00x00x00x00x00x00 xF9x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xFFxFFxF FxFFxFFxFFxFFxFFx00x00x00x00x00x00x00x00x00x00x00x00x00 x00x00x00xF9x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0 0x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x03x00 x00x00x00x00x00x00x04x00x00x00x00x00x00x00)x01x00x00x00x 00x00x00x00x00x00x00x03x00x00x00x00x00x00x00xF1x00x00x00
  53. 53. == disasm: #<ISeq:the_sum@(irb)>================================== 0000 trace 8 ( 54) 0002 trace 1 ( 55) 0004 putobject_OP_INT2FIX_O_1_C_ 0005 putobject_OP_INT2FIX_O_1_C_ 0006 opt_plus <callinfo!mid:+, argc:1, ARGS_SIM <callcache> 0009 putobject_OP_INT2FIX_O_1_C_ 0010 opt_plus <callinfo!mid:+, argc:1, ARGS_SIM <callcache> 0013 putobject_OP_INT2FIX_O_1_C_ 0014 opt_plus <callinfo!mid:+, argc:1, ARGS_SIM <callcache> 0017 trace 16
  54. 54. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… opt_plus <callinfo!mid:+, argc:1… opt_plus <callinfo!mid:+, argc:1...
  55. 55. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1...
  56. 56. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1...
  57. 57. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  58. 58. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  59. 59. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  60. 60. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  61. 61. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  62. 62. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  63. 63. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  64. 64. putobject_OP_INT2FIX_O_1_C_ putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1… putobject_OP_INT2FIX_O_1_C_ opt_plus <callinfo!mid:+, argc:1... n1 > n2 > p1 > n3 > p2 > n4 > p3
  65. 65. Recursão?
  66. 66. Recursão: Capacidade que uma rotina (função ou método) possui de invocar a si mesma.
  67. 67. Recursão:
  68. 68. Condição de parada: Hi Fulano! Hi Fulano! Hi Fulano!
  69. 69. Recursão vs Iteração
  70. 70. Como contar a quantidade de itens em uma lista?
  71. 71. Array : Iteração :
  72. 72. Iteração : Array : 4
  73. 73. Array : 4 Iteração :
  74. 74. Iteração :Array : 4
  75. 75. Iteração : Array : 4
  76. 76. Transformar todas as letras em maiúsculas: ["A", "B", "C",
  77. 77. Mas no dia a dia não fazemos exatamente assim...
  78. 78. Como realmente fazemos:
  79. 79. E com recursão?
  80. 80. Head / Tail
  81. 81. “A” Hea d Tail “B” Hea d
  82. 82. “A” Hea d Tail
  83. 83. “A” Hea d Tail
  84. 84. “A” Hea d Tail
  85. 85. Como contar a quantidade de itens em uma lista?
  86. 86. count(["A", "B", "C", "D"]) count(["B", "C", "D"]) count(["C", "D"]) count(["D"]) count([])
  87. 87. 1 + count(["B", "C", "D"]) 1 + 1 + count(["D", "D"]) 1 + 1 + 1 + count(["D"]) 1 + 1 + 1 + 1 + count([]) 1 + 1 + 1 + 1 + 0 4
  88. 88. Como somar todos os itens de uma lista?
  89. 89. 1 + sum([2, 2, 2]) 1 + 2 + sum([2, 2]) 1 + 2 + 2 + sum([2]) 1 + 2 + 2 + 2 + sum([]) 1 + 2 + 2 + 2 + 0 7
  90. 90. E por aí vai...
  91. 91. Stack Overflow
  92. 92. Stack Overflow 1 + count(["B", "C", "D"]) 1 + count(["C", "D"]) 1 + count(["D"]) 1 + count([]) 0 Tamanho do seu Stack
  93. 93. Stack Overflow 1 + count(["B", "C", "D"]) 1 + count(["C", "D"]) 1 + count(["D"]) 1 + count([]) 0 Stack Overflow
  94. 94. Stack Overflow 1 + count(["B", "C", "D"]) 1 + count(["C", "D"]) 1 + count(["D"]) 1 + count([]) 0 stack level too deep (SystemStackErro r)
  95. 95. Stack Overflow file.rb:7:in `eval': stack level too deep (SystemStackError) from file.rb:7:in `<main>'
  96. 96. Stack Overflow stack level too deep (SystemStackErro r) s 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +
  97. 97. E aí?
  98. 98. Opção 1: Aumentar o tamanho do Stack
  99. 99. ulimit -all core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31321 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200
  100. 100. RubyVM::DEFAULT_PA RAMS { thread_vm_stack_size: 1048576, thread_machine_stack_size: 1048576, fiber_vm_stack_size: 131072, fiber_machine_stack_size: 524288
  101. 101. Opção 2: Tail Call Optimization
  102. 102. c Tail Call Optimization 1 + count(["B", "C", "D"]) 1 + count(["C", "D"]) 1 + count(["D"]) 1 + count([]) 0 stack level too deep (SystemStackErro r)
  103. 103. c
  104. 104. Tail Call Optimizationcount(["A", "B", "C", "D"], 0) count(["B", "C", "D"], 1) count(["C", "D"], 2) count(["D"], 3) count([], 4) 4 Tamanho do seu Stack Reaproveitament o do seu Stack
  105. 105. file.rb:11:in `count': stack level too deep (SystemStackError) from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' ... 8723 levels... from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:11:in `count' from file.rb:17:in `<main>'
  106. 106. Precisamos compilar o nosso código com instruções específicas para a RubyVM / YARV
  107. 107. == disasm: #<ISeq:count@ppt/tco.rb>============================= local table (size: 5, argc: 1 [opts: 1, rest: -1, post: 0, block kwrest: -1]) [ 5] list<Arg> [ 4] acc<Opt=0> [ 3] head [ 2] tail 0000 putobject_OP_INT2FIX_O_0_C_ 0001 setlocal_OP__WC__0 4 0003 trace 8 0005 trace 1 0007 getlocal_OP__WC__0 5 0009 opt_empty_p <callinfo!mid:empty?, argc:0, ARGS_SIMPLE> 0012 branchunless 21 0014 nop 0015 nop 0016 getlocal_OP__WC__0 4 0018 trace 16 0020 leave 0021 trace 1 0023 getlocal_OP__WC__0 5 0025 opt_send_without_block <callinfo!mid:shift, argc:0, ARGS_SI 0028 setlocal_OP__WC__0 3 0030 trace 1 0032 getlocal_OP__WC__0 5 0034 setlocal_OP__WC__0 2
  108. 108. == disasm: #<ISeq:count@ppt/tco.rb>============================= local table (size: 5, argc: 1 [opts: 1, rest: -1, post: 0, block kwrest: -1]) [ 5] list<Arg> [ 4] accc<Opt=0> [ 3] head [ 2] tail 0000 putobject_OP_INT2FIX_O_0_C_ 0001 setlocal_OP__WC__0 4 0003 trace 8 0005 trace 1 0007 getlocal_OP__WC__0 5 0009 opt_empty_p <callinfo!mid:empty?, argc:0, ARGS_SIMPLE> 0012 branchunless 21 0014 nop 0015 nop 0016 getlocal_OP__WC__0 4 0018 trace 16 0020 leave 0021 trace 1 0023 getlocal_OP__WC__0 5 0025 opt_send_without_block <callinfo!mid:shift, argc:0, ARGS_SI 0028 setlocal_OP__WC__0 3 0030 trace 1 0032 getlocal_OP__WC__0 5 0034 setlocal_OP__WC__0 2
  109. 109. Acompanhar eventos durante a execução do código internamente na VM stackprof ruby-prof
  110. 110. trace + tail call optimization =
  111. 111. == disasm: #<ISeq:count@<compiled>>=============================== local table (size: 5, argc: 1 [opts: 1, rest: -1, post: 0, block: kwrest: -1]) [ 5] list<Arg> [ 4] acc<Opt=0> [ 3] head [ 2] tail 0000 putobject_OP_INT2FIX_O_0_C_ 0001 setlocal_OP__WC__0 4 0003 getlocal_OP__WC__0 5 0005 opt_empty_p <callinfo!mid:empty?, argc:0, ARGS_SIMPLE>, 0008 branchunless 15 0010 nop 0011 nop 0012 getlocal_OP__WC__0 4 0014 leave 0015 getlocal_OP__WC__0 5 0017 opt_send_without_block <callinfo!mid:shift, argc:0, ARGS_SIMP 0020 setlocal_OP__WC__0 3 0022 getlocal_OP__WC__0 5 0024 setlocal_OP__WC__0 2 0026 putself 0027 getlocal_OP__WC__0 2 0029 getlocal_OP__WC__0 4 0031 putobject_OP_INT2FIX_O_1_C_ 0032 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <call 0035 opt_send_without_block <callinfo!mid:count, argc:2, FCALL|ARG
  112. 112. 0008 branchunless 15 0010 nop 0011 nop 0012 getlocal_OP__WC__0 4 0014 leave 0015 getlocal_OP__WC__0 5 0017 opt_send_without_block <callinfo!mid:shift, argc:0, ARGS_SIMP 0020 setlocal_OP__WC__0 3 0022 getlocal_OP__WC__0 5 0024 setlocal_OP__WC__0 2 0026 putself 0027 getlocal_OP__WC__0 2 0029 getlocal_OP__WC__0 4 0031 putobject_OP_INT2FIX_O_1_C_ 0032 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <call 0035 opt_send_without_block <callinfo!mid:count, argc:2, FCALL|ARG <callcache> 0038 leave
  113. 113. 0008 branchunless 15 0010 nop 0011 nop 0012 getlocal_OP__WC__0 4 0014 leave 0015 getlocal_OP__WC__0 5 0017 opt_send_without_block <callinfo!mid:shift, argc:0, ARGS_SIMP 0020 setlocal_OP__WC__0 3 0022 getlocal_OP__WC__0 5 0024 setlocal_OP__WC__0 2 0026 putself 0027 getlocal_OP__WC__0 2 0029 getlocal_OP__WC__0 4 0031 putobject_OP_INT2FIX_O_1_C_ 0032 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <call 0035 opt_send_without_block <callinfo!mid:count, argc:2, FCALL|ARG <callcache> 0038 leave
  114. 114. == disasm: #<ISeq:count@<compiled>>=============================== local table (size: 5, argc: 1 [opts: 1, rest: -1, post: 0, block: kwrest: -1]) [ 5] list<Arg> [ 4] acc<Opt=0> [ 3] head [ 2] tail 0000 putobject_OP_INT2FIX_O_0_C_ 0001 setlocal_OP__WC__0 4 0003 getlocal_OP__WC__0 5 0005 opt_empty_p <callinfo!mid:empty?, argc:0, ARGS_SIMPLE>, 0008 branchunless 15 0010 nop 0011 nop 0012 getlocal_OP__WC__0 4 0014 leave 0015 getlocal_OP__WC__0 5 0017 opt_send_without_block <callinfo!mid:shift, argc:0, ARGS_SIMP 0020 setlocal_OP__WC__0 3 0022 getlocal_OP__WC__0 5 0024 setlocal_OP__WC__0 2 0026 putself 0027 getlocal_OP__WC__0 2 0029 getlocal_OP__WC__0 4 0031 putobject_OP_INT2FIX_O_1_C_ 0032 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <call 0035 opt_send_without_block <callinfo!mid:count, argc:2, FCALL|TAI
  115. 115. ess 15 OP__WC__0 4 OP__WC__0 5 ( 5) without_block <callinfo!mid:shift, argc:0, ARGS_SIMPLE>, <callcache OP__WC__0 3 OP__WC__0 5 ( 6) OP__WC__0 2 ( 8) OP__WC__0 2 OP__WC__0 4 _OP_INT2FIX_O_1_C_ <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache> without_block <callinfo!mid:count, argc:2, FCALL|TAILCALL|ARGS_SIMP
  116. 116. 100000 0
  117. 117. Por quê?
  118. 118. Mais rápido que iterar?
  119. 119. user system total real .each: 16.480000 0.000000 16.480000 ( 16.492415) recursion: 26.280000 0.380000 26.660000
  120. 120. Maior proximidade com conceitos de linguagens funcionais
  121. 121. Considerada uma forma elegante de resolver problemas
  122. 122. Quicksort em C utilizando iteração
  123. 123. Quicksort em Haskell utilizando recursão
  124. 124. Maneira de lidar com diferentes estruturas de dados
  125. 125. Listas Ligadas
  126. 126. Grafos
  127. 127. Árvores Binárias
  128. 128. Mais uma maneira de resolver problemas e entender os detalhes da linguagem
  129. 129. Referências: - RubyVM::InstructionSequence http://ruby-doc.org/core-2.3.1/RubyVM/InstructionSequence.html - Inline caching in MRI http://tenderlovemaking.com/2015/12/23/inline-caching-in-mri.html - Ruby, Trace, Leave, Oh my! http://kgrz.io/2014/04/19/ruby-trace-leave-oh-my.html
  130. 130. Referências: - Tail Call Optimization in Ruby http://nithinbekal.com/posts/ruby-tco/ - Tailin' Ruby http://timelessrepo.com/tailin-ruby - Tail Call Optimization in Ruby: Deep Dive http://blog.tdg5.com/tail-call-optimization-in-ruby-deep-dive/
  131. 131. Referências: - TCOMethod Simplifies compiling code with tail call optimization in MRI Ruby https://github.com/tdg5/tco_method - Hamster Efficient, Immutable, Thread-Safe Collection classes for Ruby https://github.com/hamstergem/hamster - Functional Ruby A gem for adding functional programming tools to Ruby. Inspired by Erlang, Clojure, Haskell, and Functional Java. https://github.com/jdantonio/functional-ruby
  132. 132. Obrigado! gbaptista.com.br Twitter: @guilhermebps github.com/gbaptista linkedin.com/in/guilhermebaptista

×