Code OptimizationsRuby128 minutes
Huh? What’s that?2
Why would I want to do that?MoneyResourcesHardwarePeople (Developers)TimeSpeed of operationDeveloper takes to figure out what’s going onKarmaNo one wants to write bad code!3
4Ruby
Interpolation over Concatenationputs "This string embeds #{a} and #{b} through interpolation"# => fasterputs "This string concatenates "<< a <<" and "<< b  # => slowerputs "This string concatenates “+ a +" and "+ b  # => slower5
Destructive Operations!hash = {}hash =hash.merge({1=>2}) # duplicates the original hashhash.merge!({1=>2}) # equivalent to previous line, and fasterstr="string to gsub"str=str.gsub(/to/, 'copy') # duplicate string and reassigns itstr.gsub!(/to/, 'copy') # same effect, but no object duplication6
Benchmark everythingrequire 'benchmark'n =100000Benchmark.bm do |x| x.report('copy') { n.timesdo ; h = {}; h =h.merge({1=>2}); end }   x.report('no copy') { n.timesdo ; h = {}; h.merge!({1=>2}); end }end#          user       system     total       real# copy    0.460000   0.180000   0.640000  (0.640692)# no copy 0.340000   0.120000   0.460000  (0.463339)7
Symbols whenever possible'foo'.object_id# => 23233310'foo'.object_id# => 23228920:foo.object_id# => 239298:foo.object_id# => 2392988
Array joins[1, 2, 3] * 3# => [1, 2, 3, 1, 2, 3, 1, 2, 3][1, 2, 3] * '3'# => "13233" %w{thisisatest} * ", "# => "this, is, a, test" h = { :name=>"Fred", :age=>77 }h.map { |i| i * "=" } * "\n"# => "age=77\nname=Fred"9
Everything is an object!defadd(adder, addee)  adder +addeeend add(3,5) # => 8classFixnumdefadd(num)self+ numendend3.add(5)# => 810
Use ranges instead of complex comparisons for numbers# No more if x > 1000 && x < 2000 nonsense. Instead:year =1972puts  case yearwhen1970..1979:"Seventies"when1980..1989:"Eighties"when1990..1999:"Nineties"end11
Ruby logicdefis_odd(x)    if x % 2==0returnfalseelsereturntrueendenddefis_odd(x)  x % 2==0?false:trueenddefis_odd(x)  x % 2!=0end12classFixnumdef odd?self % 2!=0endend2.odd? # => false
Enumerate single object# [*items] converts a single object into an array. And if the object is an array, keeps it as it is.[*items].each do |item|# ...end13
14Rails
CachingPage CachingFragment CachingAction CachingCaching into Local / Instance Variable15# Makes a database query only if @current_user is nildefcurrent_user@current_user||=User.find(session[:user_id])end
Don’t limit yourself to ActiveRecordUse performance boosting database features like: Stored proceduresFunctionsX-query16
Finders are great but be carefulRetrieve only the information that you need. Don’t kill your database with too many queries. Use eager loading.Avoid dynamic finders like MyModel.find_by_*.Need an optimized query? Run MyModel.find_by_sql.17#This will generates only one query,# rather than Post.count + 1 queriesfor post inPost.find(:all, :include=> [ :author, :comments ])# Do something with postend
Control your controllersDon’t let them become the God classes.Lesser instance variables.Slimmer the better.Appropriate code in appropriate controller.18
19And of course!
20Obey design principles.Always code in context (Objects). It is the best way to model your solution.Avoid “Quick and dirty”.Understand that no good can ever come out of duplication. Be it code, design, data and most importantly effort.Simplicity is the key.Enjoy coding!
21Slidesslideshare.net/ihower/rails-best-practicesslideshare.net/ihower/practical-rails2-350619slideshare.net/preston.lee/logical-programming-with-ruby-prologRuby BooksThe Ruby Wayby Hal Edwin Fulton, Guy HurstThe Rails Way by Obie FernandezDesign Patterns in Rubyby Russ OlsenSoftware ConstructionCode Complete 2 by Steve McConnellThe Pragmatic Programmer: From Journeyman to Masterby Andrew Hunt

Ruby Code Optimizations (for beginners)

  • 1.
  • 2.
  • 3.
    Why would Iwant to do that?MoneyResourcesHardwarePeople (Developers)TimeSpeed of operationDeveloper takes to figure out what’s going onKarmaNo one wants to write bad code!3
  • 4.
  • 5.
    Interpolation over Concatenationputs"This string embeds #{a} and #{b} through interpolation"# => fasterputs "This string concatenates "<< a <<" and "<< b # => slowerputs "This string concatenates “+ a +" and "+ b # => slower5
  • 6.
    Destructive Operations!hash ={}hash =hash.merge({1=>2}) # duplicates the original hashhash.merge!({1=>2}) # equivalent to previous line, and fasterstr="string to gsub"str=str.gsub(/to/, 'copy') # duplicate string and reassigns itstr.gsub!(/to/, 'copy') # same effect, but no object duplication6
  • 7.
    Benchmark everythingrequire 'benchmark'n=100000Benchmark.bm do |x| x.report('copy') { n.timesdo ; h = {}; h =h.merge({1=>2}); end } x.report('no copy') { n.timesdo ; h = {}; h.merge!({1=>2}); end }end# user system total real# copy 0.460000 0.180000 0.640000 (0.640692)# no copy 0.340000 0.120000 0.460000 (0.463339)7
  • 8.
    Symbols whenever possible'foo'.object_id#=> 23233310'foo'.object_id# => 23228920:foo.object_id# => 239298:foo.object_id# => 2392988
  • 9.
    Array joins[1, 2,3] * 3# => [1, 2, 3, 1, 2, 3, 1, 2, 3][1, 2, 3] * '3'# => "13233" %w{thisisatest} * ", "# => "this, is, a, test" h = { :name=>"Fred", :age=>77 }h.map { |i| i * "=" } * "\n"# => "age=77\nname=Fred"9
  • 10.
    Everything is anobject!defadd(adder, addee) adder +addeeend add(3,5) # => 8classFixnumdefadd(num)self+ numendend3.add(5)# => 810
  • 11.
    Use ranges insteadof complex comparisons for numbers# No more if x > 1000 && x < 2000 nonsense. Instead:year =1972puts case yearwhen1970..1979:"Seventies"when1980..1989:"Eighties"when1990..1999:"Nineties"end11
  • 12.
    Ruby logicdefis_odd(x) if x % 2==0returnfalseelsereturntrueendenddefis_odd(x) x % 2==0?false:trueenddefis_odd(x) x % 2!=0end12classFixnumdef odd?self % 2!=0endend2.odd? # => false
  • 13.
    Enumerate single object#[*items] converts a single object into an array. And if the object is an array, keeps it as it is.[*items].each do |item|# ...end13
  • 14.
  • 15.
    CachingPage CachingFragment CachingActionCachingCaching into Local / Instance Variable15# Makes a database query only if @current_user is nildefcurrent_user@current_user||=User.find(session[:user_id])end
  • 16.
    Don’t limit yourselfto ActiveRecordUse performance boosting database features like: Stored proceduresFunctionsX-query16
  • 17.
    Finders are greatbut be carefulRetrieve only the information that you need. Don’t kill your database with too many queries. Use eager loading.Avoid dynamic finders like MyModel.find_by_*.Need an optimized query? Run MyModel.find_by_sql.17#This will generates only one query,# rather than Post.count + 1 queriesfor post inPost.find(:all, :include=> [ :author, :comments ])# Do something with postend
  • 18.
    Control your controllersDon’tlet them become the God classes.Lesser instance variables.Slimmer the better.Appropriate code in appropriate controller.18
  • 19.
  • 20.
    20Obey design principles.Alwayscode in context (Objects). It is the best way to model your solution.Avoid “Quick and dirty”.Understand that no good can ever come out of duplication. Be it code, design, data and most importantly effort.Simplicity is the key.Enjoy coding!
  • 21.
    21Slidesslideshare.net/ihower/rails-best-practicesslideshare.net/ihower/practical-rails2-350619slideshare.net/preston.lee/logical-programming-with-ruby-prologRuby BooksThe RubyWayby Hal Edwin Fulton, Guy HurstThe Rails Way by Obie FernandezDesign Patterns in Rubyby Russ OlsenSoftware ConstructionCode Complete 2 by Steve McConnellThe Pragmatic Programmer: From Journeyman to Masterby Andrew Hunt