Attributes Unwrapped: Lessons under the surface of active record
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Attributes Unwrapped: Lessons under the surface of active record

on

  • 1,339 views

Ведущий разработчик Ruby on Rails (Rails Core member) Джон Лейтон не так давно работал над совершенствованием реализации ...

Ведущий разработчик Ruby on Rails (Rails Core member) Джон Лейтон не так давно работал над совершенствованием реализации работы с атрибутами в Active Record. Он расскажет о своем опыте работы над важной для производительности областью Rails, даст советы и расскажет о техниках, которые могут быть применены к собственным приложениям слушателей.
Говоря о будущем, Джон также расскажет о своих идеях по изменению API работы с атрибутами в лучшую сторону; эти изменения могут появиться в Rails 4.0.

Statistics

Views

Total Views
1,339
Views on SlideShare
1,339
Embed Views
0

Actions

Likes
3
Downloads
13
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Attributes Unwrapped: Lessons under the surface of active record Presentation Transcript

  • 1. Attributes Unwrapped
  • 2. @jonleighton
  • 3. I lied to you
  • 4. Measure
  • 5. MeasureRefactor
  • 6. MeasureRefactorOptimise
  • 7. LET’S DO SCIENCE
  • 8. gem rails, 3.2.0require active_recordActiveRecord::Base .establish_connection( :adapter => sqlite3, :database => :memory:)
  • 9. ActiveRecord::Schema.define do create_table :posts do |t| t.string :title endendclass Post < ActiveRecord::Baseendp = Post.create(:title => "lol")
  • 10. require benchmarkn = 1_000_000Benchmark.report(20) do |r| r.report(attribute) do n.times { p.title } end r.report(read_attribute) do n.times { p[:title] } endend
  • 11. attribute 1.09 sread_attribute 2.87 s
  • 12. gem installbenchmark_suite
  • 13. require benchmark/ipsBenchmark.ips do |r| r.report(attribute) do p.title end r.report(read_attribute) do p[:title] endend
  • 14. attribute 828,648read_attribute 299,856
  • 15. Ruby 1.9
  • 16. Ruby 1.8
  • 17. Ruby 1.8 oops!
  • 18. define_method
  • 19. method compilation
  • 20. create_table :roflcopters do |t| t.string " ROFL:ROFL:ROFL:ROFL" t.string " _^____ " t.string " L __/ [] " t.string "LOL===_ " t.string " L _________] " t.string " I I " t.string " --------/ "end
  • 21. if compilable? class_eval <<-STR def #{attr_name} ... end STRelse define_method attr_name do ... endend
  • 22. attr_name =~/A[a-zA-Z_]w*[!?=]?z/
  • 23. :title =~/A[a-zA-Z_]w*[!?=]?z/
  • 24. Ruby 1.9:title =~ /.../# => true
  • 25. Ruby 1.8:title =~ /.../# => false
  • 26. def __temp__ ...endalias "@#>" :__temp__undef_method :__temp__
  • 27. DOdef __temp__ NT ... USend E THalias "@#>" :__temp__ ISundef_method :__temp__
  • 28. API Changes
  • 29. def title self[:title].upcaseend
  • 30. def title super.upcaseend
  • 31. module A def foo "bar" endend
  • 32. class B include A def foo super.upcase endend
  • 33. Don’t fight Ruby <3 <3 <3
  • 34. #read_attribute#[]
  • 35. def read_attribute(name) name = "_#{name}" if respond_to?(name) send(name) else # other stuff endend
  • 36. Module.new
  • 37. def read_attribute(name) mod = self.class.methods_module if mod.respond_to?(name) mod.send(name, @attributes) else # other stuff endend
  • 38. Module.new.respond_to?(:name)# => true
  • 39. Module.new { extend self }
  • 40. Module.new { extend self }mod.method_defined?(:name)
  • 41. IN SAModule.new { extend self } NE HA CKmod.method_defined?(:name)
  • 42. Still too slow ☹
  • 43. gem installperftools.rb
  • 44. if attr_name == id attr_name = self.class.primary_keyend
  • 45. No code is faster than no code
  • 46. def title cast @attributes[title]end
  • 47. def title cast @attributes[:title]end
  • 48. class A def initialize @attributes = { :foo => 1 } end def foo @attributes[:foo] endend
  • 49. class B def initialize @attributes = { foo => 1 } end def foo @attributes[foo] endend
  • 50. Benchmark.ips do |r| r.report(symbol) { a.foo } r.report(string) { b.foo }end
  • 51. code = "@attributes[foo]"iseq = RubyVM::InstructionSequence .compile(code)puts iseq.disassemble
  • 52. trace 1getinstancevariable :@attributesputstring "foo"opt_aref <ic:2>leave
  • 53. trace 1getinstancevariable :@attributesputobject :fooopt_aref <ic:2>leave
  • 54. DEFINE_INSNputstring(VALUE str)()(VALUE val){ val = rb_str_resurrect(str);}
  • 55. DEFINE_INSNputobject(VALUE val)()(VALUE val){ /* */}
  • 56. code = "@attributes[foo]"compiled = Rubinius::Compiler .compile_string(code)puts compiled.decode
  • 57. push_ivar 0push_literal "foo"string_dupsend_stack :[], 1poppush_trueret
  • 58. push_ivar 0push_literal :foosend_stack :[], 1poppush_trueret
  • 59. jruby --bytecode -e "@attributes[foo]"
  • 60. RubyString
  • 61. RubyStringRubySymbol
  • 62. Performance problems are a code smell
  • 63. Be a scientist
  • 64. But...
  • 65. Avoid roflscaling!
  • 66. ER! OV S ITThanks!
  • 67. Thanks! IT S OV E R!(♥ @tenderlove ♥)