Pro Yearly is on sale from $80 to $50! »

Ruby 2.0 on Rails in Production

Ruby 2.0 on Rails in Production

Slides for RedDotRubyConf talk "Ruby 2.0 on Rails in Production" http://www.reddotrubyconf.com/schedule#amatsuda

76a777ff80f30bd3b390e275cce625bc?s=128

Akira Matsuda

June 08, 2013
Tweet

Transcript

  1. Ruby 2.0 on Rails in Production Akira Matsuda

  2. % ruby -v Who here are already using Ruby 2.0

    in production?
  3. % ruby -v Who here are still using 1.8?

  4. None
  5. begin

  6. Ruby 2.0 goodness Performance Stability Compatibility New features

  7. Performance

  8. None
  9. ※ taken from @mirakui's slide at RubyKaigi 2013 https://speakerdeck.com/mirakui/high-performance-rails?slide=7

  10. ※ taken from @mrkn's slide at OedoRubyKaigi 03 https://speakerdeck.com/mrkn/what-a-hard-work-to-make-the-recipe- sharing-service-available-on-ruby-1-dot-9-3?slide=128

  11. rails command boot time # ruby 1.9.3p429 % time rails

    r '1' rails r '1' 7.00s user 1.67s system 99% cpu 8.701 total % time rails r '1' rails r '1' 7.03s user 1.64s system 99% cpu 8.698 total % time rails r '1' rails r '1' 7.01s user 1.66s system 99% cpu 8.710 total # ruby 2.0.0p195 % time rails r '1' rails r '1' 4.80s user 1.29s system 99% cpu 6.124 total % time rails r '1' rails r '1' 4.77s user 1.28s system 99% cpu 6.073 total % time rails r '1' rails r '1' 4.78s user 1.29s system 99% cpu 6.099 total
  12. Stability

  13. Stability Fact: 2.0.0 was a "stable" release

  14. 1.9.0 was not 1.9.0: unstable 1.9.1: unstable 1.9.2: stable 1.9.3:

    stable 2.0.0: stable 2.1.0: stable (?)
  15. Stability 2.0.0-p195 was released last month by @nagachika

  16. None
  17. None
  18. Stability 2.0.0 is no more p0 and so it's ready

    to use in production
  19. Branch Maintenance Policies 1.8.7: maintained by @shyouhei, will be dead

    soon 1.8.8: no plan 1.9.0: dead 1.9.1: dead 1.9.2: maintained by @yugui, dead (?) 1.9.3: maintained by @unak 1.9.4: no plan 2.0.0: maintained by @nagachika 2.0.1: no plan 2.1.0: managed by @naruse
  20. 1.9.3 Released by @yugui Maintained by @unak (aka. usa) Sponsored

    by Ruby Association
  21. None
  22. None
  23. 2.0.0 Released by @mametter (aka. mame) Maintained by @nagachika

  24. None
  25. None
  26. 2.1.0 Would be released by @nalsh (aka. naruse) Would be

    released in December this year
  27. None
  28. "TRICK 2013" in RubyKaigi Results: http:// www.slideshare.net/mametter/ trick2013-results Winners: https://github.com/tric/

    trick2013
  29. @unak (usa) $ruby.is_a?(Object){|oriented| language}

  30. @mametter (mame) eval$C=%q(at_exit{ open("/dev/dsp","wb"){|g|h=[0]*80 $><<"\s"*18+"eval$C=%q(#$C);S=%:" (S<<m=58).lines{|l|s=[128]*n=20E2 t=0; h.map!{|v|d=?!==l[ t]?1 :(l[

    t]== ?#)? 0*v= 6:03 (v<1 ?[]: 0..n -1). each {|z| s[z] +=2* M.sin(($*[0] ||1) .to_f*M.sin(y= 40*(z+m)*2** (t/12E0)/463)+ y)*(v-z*d/n)}; t+=1;v-d};m+= n;g.flush<<(s. pack"C*"); puts(l)}}};M= Math);S=%: Jesu, Joy of Man's Desiring Johann Sebastian Bach # | # | # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # | | | # | #| # # # | # | | | # | | # # # # # # | | # | | | # # # # # # | | | # | | # # # # # | | # | | # # | # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | # # # # # | | | # | # | # # # # # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  31. Compatibility

  32. Compatibility "100% compatible" (Ruby level) magic comment

  33. None
  34. 99.9% compatible Default Ruby source le encoding to utf-8 [Feature

    #6679]
  35. Hello! puts '͜Μʹͪ͸ʂ'

  36. Hello...? % ruby -v hello_utf8.rb ruby 1.8.7 (2012-06-29 patchlevel 370)

    [i686-darwin12.2.1] ͜Μʹͪ͸ʂ % ruby -v hello_utf8.rb ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0] encoding_utf8.rb:1: invalid multibyte char (US-ASCII)
  37. Magic comment # encoding: utf-8 puts '͜Μʹͪ͸ʂ'

  38. ͜Μʹͪ͸ɺ1.9.3! % ruby -v hello_utf8.rb ruby 1.9.3p429 (2013-05-15 revision 40747)

    [x86_64-darwin12.3.0] ͜Μʹͪ͸ʂ
  39. Hello! puts '͜Μʹͪ͸ʂ'

  40. Hello...? % ruby -v hello_utf8.rb ruby 1.8.7 (2012-06-29 patchlevel 370)

    [i686-darwin12.2.1] ͜Μʹͪ͸ʂ % ruby -v hello_utf8.rb ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-darwin12.3.0] encoding_utf8.rb:1: invalid multibyte char (US-ASCII) % ruby -v hello_utf8.rb ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.3.0] ͜Μʹͪ͸ʂ
  41. Incompatibility s = "\xE3\x81\x82" p s, s.size

  42. Incompatibility % ruby -v encoding_binary.rb ruby 1.9.3p429 (2013-05-15 revision 40747)

    [x86_64-darwin12.3.0] "\xE3\x81\x82" 3 % ruby -v encoding_binary.rb ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.3.0] "͋" 1
  43. Tiny Print Debugging Tip s = "\xE3\x81\x82" # p s,

    s.size p str: s, size: s.size
  44. Tiny Print Debugging Tip % ruby encoding_binary.rb {:str=>"͋", :size=>1} (by

    @yhara: http://route477.net/d/?date=20130206#p01)
  45. Compatibility (GC bug) Ruby 2.0 is so compatible with 1.9.3

    that even known bugs are compatible!
  46. "GC.disable_lazy_sweep" https://gist.github.com/mrkn/ 5096076

  47. New features

  48. New Features (Re nements) Module#prepend Keyword arguments Enumerable#lazy

  49. Re nements

  50. None
  51. Module#prepend

  52. Module#prepend Good for Rails plugins You can replace alias_method_chain with

    this
  53. AMC class A def foo puts 'foo' end end class

    A def foo_with_bar foo_without_bar puts ‘bar’ end alias_method_chain :foo, :bar end A.new.foo #=> foo bar
  54. Module#prepend class A def foo; puts 'foo'; end end module

    Bar def foo super puts 'bar' end end class A prepend Bar end A.new.foo #=> foo bar
  55. Keyword arguments

  56. Method#parameters since 1.9.1

  57. Method#parameters class C def m(a, b = 1, c =

    nil) end end C.new.method(:m).parameters #=> [[:req, :a], [:opt, :b], [:opt, :c]]
  58. asakusarb/action_args

  59. None
  60. Initial implementation module AbstractController class Base def send_action(method_name, *args) return

    send method_name, *args unless args.blank? values = method(method_name).parameters.map(&:last).map {|k| params[k]} send method_name, *values end end end
  61. Test Patterns params = {a: '1', b: '2'} def m

    end #=> [] def m(a) end #=> ['1'] def m(a = 'a') end #=> ['1'] def m(c = 'c') end #=> expected: ['c'], actual: [nil]
  62. Don't add to the arguments if (type == :opt) &&

    !params.has_key? params = {a: '1', b: '2'} def m(c = 'c') end #=> ['c'] def m(a, b) end #=> ['1', '2'] def m(a, b = 'b') end #=> ['1', '2'] def m(a, c = 'c') end #=> ['1', 'c'] def m(a = 'a', b = 'b') end #=> ['1', '2'] def m(c = 'c', d = 'd') end #=> ['c', 'd'] def m(c = 'c', a) end #=> expected: ['c', '1'], actual: ['1']
  63. Default value can't be determined in parse / compile phase

    def foo(x = rand(3))
  64. RubyVM::InstructionSequence # warning: Do never use this black magic!! def

    foo(x = 'xx', y = :yy, z = 1); end ary = RubyVM::InstructionSequence.of(method(:foo)).to_a default_args = ary[11][1] bytecode = ary[13] p default_args #=> [:label_0, :label_4, :label_8, :label_11] p bytecode #=> [:label_0, 2, [:putstring, "xx"], [:setlocal_OP__WC__0, 4], :label_4, [:putobject, :yy], [:setlocal_OP__WC__0, 3], :label_8, [:putobject_OP_INT2FIX_O_1_C_], [:setlocal_OP__WC__0, 2], :label_11, [:trace, 8], [:putnil], [:trace, 16], [:leave]]
  65. method.parameters.reverse_each do |type, key| do the same thing params =

    {a: '1', b: '2'} def m(c = 'c', a) end => ['c', '1']
  66. We needed to do this because, Method parameters are just

    an Array So the order matters It's a pain I wish if the method parameter is more like a Hash, labeled by the de ned method argument names
  67. OK, that's called "Keyword arguments"

  68. Keyword arguments # traditional method def m(a, b = 'b',

    c = 'c') end m('1', '2', '3') # kwargs def m(a, b: 'b', c: 'c') end m('1', b: '2', c: '3')
  69. Keyword arguments Optional parameters can be written as a Hash.

    Order doesn't matter action_args now supports kwargs, so you can use it in your controller code
  70. kwargs and Rails Rewriting Rails code using kwargs More comprehensible

    API def foo(options_with_some_unknown_keys_and_defaults = {}) def bar(*values_maybe_or_maybe_not_with_options) ⊗ def foo(x: 1, y: 2, z: 2) def bar(*values, **options)
  71. kwargs and Rails (AS) # AS/lib/active_support/core_ext/class/attribute_accessors.rb - def cattr_reader(*syms) -

    options = syms.extract_options! + def cattr_reader(*syms, instance_reader: true, instance_accessor: true) ... - unless options[:instance_reader] == false || options[:instance_accessor] == false + unless (instance_reader == false) || (instance_accessor == false)
  72. kwargs and Rails (AMo) # AMo/lib/active_model/validations/validates.rb - def validates(*attributes) -

    defaults = attributes.extract_options!.dup + def validates(*attributes, **defaults)
  73. kwargs and Rails (AP) # AP/lib/action_view/helpers/text_helper.rb - def cycle(first_value, *values)

    - options = values.extract_options! - name = options.fetch(:name, 'default') - + def cycle(first_value, *values, name: 'default')
  74. A pitfall I found

  75. kwargs and Rails (:if, :unless) User.validates_presence_of :name, :if => ->

    { true } # AMo/lib/active_model/validations/presence.rb - def validates_presence_of(*attr_names) + def validates_presence_of(*attr_names, if: true, unless: false, on: nil, strict: nil)
  76. :if!? def m(if: true) end

  77. :if!? def m(if: true) if if ... end end #=>

    "syntax error, unexpected keyword_end"
  78. :if!? def m(if: true) p if end #=> "syntax error,

    unexpected keyword_end"
  79. kwargs and Rails (:end)

  80. kwargs and Rails (:end) # actionpack/lib/action_view/helpers/date_helper.rb - def build_options(selected, options

    = {}) - options = { - leading_zeros: true, ampm: false, use_two_digit_numbers: false - }.merge!(options) - - start = options.delete(:start) || 0 - stop = options.delete(:end) || 59 - step = options.delete(:step) || 1 - leading_zeros = options.delete(:leading_zeros) + def build_options(selected, start: 0, end: 59, step: 1, leading_zeros: true, ampm: false, use_two_digit_numbers: false)
  81. :end!? def m(end: 'omg') p end end #=> "syntax error,

    unexpected keyword_end, expecting end-of-input"
  82. Enumerable#lazy

  83. Enumerable#lazy "Enumerable#lazy".topics.lazy.each {|it| I.talk it}

  84. New Features (internal) TracePoint DTrace support caller_locations debug_inspector API Memory

    inspection features
  85. None
  86. debug_inspector API

  87. The "debugger" gem Works on Ruby 1.9 Partly supports 2.0

    Own header les
  88. We created a new gem Named it "debugger2" (ko1 named

    it. Not me!) Based on new debugger API
  89. Debugger2 gem "1.0.0.beta2" Still buggy on Rails We need to

    do more debugging on the debugger...
  90. We want debugger!!!

  91. end