SlideShare a Scribd company logo
Rails Performance Best
       Practices
       http://ihower.tw
            2010/3
About Me
•           a.k.a. ihower
    • http://ihower.tw
    • http://twitter.com/ihower
    • http://github.com/ihower
• Ruby on Rails Developer since 2006
• Ruby Taiwan Community
 • http://ruby.tw
Performance Worse
       Practices

• Premature Optimization
• Guessing
• Caching everything
• Fighting the framework
Performance Guidelines
• Algorithmic improvements always beat
  code tweaks
• As a general rule, maintainability beats
  performance
• Only optimize what matters (80/20 rule)
• Measure twice, cut once
• Must be balanced with flexibility
How to improve
      performance?
• Find the target baseline
• Know where you are now
• Profile to find bottlenecks
• Remove bottlenecks
• Repeat
Agenda
•   Analysis and Measurement
•   Write Efficient Ruby code
•   Use REE 1.8.7 or Ruby 1.9
•   Use faster Ruby Library
•   Caching
•   SQL and ActiveRecord
•   Consider NoSQL storage
•   Rack and Rails Metal
•   Use HTTP server for static files
•   Front-end web performance
•   Use external programs or write inline C code
Finding the Problems:
       Analysis
Server Log Analysis
•   http://github.com/wvanbergen/request-log-analyzer
    •   Request distribution per hour
    •   Most requested
    •   HTTP methods
    •   HTTP statuses returned
    •   Rails action cache hits
    •   Request duration
    •   View rendering time
    •   Database time
    •   Process blockers
    •   Failed requests
Commercial Monitor
     Products

• New Relic
• Scout
Rack::Bug
Rails middleware which gives you an informative toolbar in your browser
MemoryLogic
Adds in proccess id and memory usage in your rails logs, great for tracking down
                               memory leaks




• http://github.com/binarylogic/memorylogic
Processing WelcomeController#index (for 127.0.0.1 at 2010-02-26 01:51:54) [GET] (mem 104792)
  Parameters: {"action"=>"index", "controller"=>"welcome"} (mem 104792)
  ...
Memory usage: 108888 | PID: 6170 (mem 108888)
Completed in 3570ms (View: 1861, DB: 1659) | 200 OK [http://localhost/] (mem 108888)
oink
   Log parser to identify actions which significantly increase VM heap size



• http://github.com/noahd1/oink
               script/oink -t 0 ~/rails-app/log/development.log

               ---- MEMORY THRESHOLD ----
               THRESHOLD: 0 MB

               -- SUMMARY --
               Worst Requests:
               1. Feb 26 02:12:45,   37360 KB, SessionsController#new
               2. Feb 26 02:12:41,   37352 KB, BooksController#hot
               3. Feb 26 02:12:21,   16824 KB, BooksController#hot
               4. Feb 26 02:12:25,   11632 KB, BooksController#hot
               5. Feb 26 02:12:19,   11120 KB, BooksController#hot
               6. Feb 26 02:12:51,   9888 KB, WelcomeController#index
               7. Feb 26 02:12:28,   7548 KB, WelcomeController#index
               8. Feb 26 02:12:23,   5120 KB, ArticlesController#index

               Worst Actions:
               4, BooksController#hot
               2, WelcomeController#index
               1, ArticlesController#index
               1, SessionsController#new
ruby-prof gem
•   a fast code profiler for Ruby. Its features include:
    •   Speed - it is a C extension
    •   Modes - call times, memory usage and object allocations.
    •   Reports - can generate text and cross-referenced html
        reports
    •   Threads - supports profiling multiple threads
        simultaneously
    •   Recursive calls - supports profiling recursive method
        calls
ruby-prof example (1)
     require 'ruby-prof'

     # Profile the code
     RubyProf.start
     ...
     # code to profile
     100.times { puts "blah" }

     result = RubyProf.stop

     # Print a flat profile to text
     printer = RubyProf::FlatPrinter.new(result)
     printer.print(STDOUT, 0)
ruby-prof example (2)
Thread ID: 2148368700
Total: 0.022092

 %self     total        self   wait   child   calls   name
 13.19      0.00        0.00   0.00    0.00       2   Readline#readline (ruby_runtime:0}
 12.16      0.01        0.00   0.00    0.00      79   RubyLex#getc (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:101}
  4.87      0.00        0.00   0.00    0.00      30   RubyLex#ungetc (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:144}
  4.52      0.00        0.00   0.00    0.00       5   RubyLex#identify_identifier (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:770}
  4.41      0.00        0.00   0.00    0.00     202   IO#write (ruby_runtime:0}
  4.03      0.02        0.00   0.00    0.02      20   IRB::SLex::Node#match_io (/opt/ruby-enterprise/lib/ruby/1.8/irb/slex.rb:204}
  4.00      0.01        0.00   0.00    0.01      28   Proc#call (ruby_runtime:0}
  2.92      0.00        0.00   0.00    0.00      20   RubyToken#Token (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-token.rb:84}
  2.85      0.00        0.00   0.00    0.00     271   String#== (ruby_runtime:0}
  2.65      0.01        0.00   0.00    0.01      14   IRB::SLex::Node#match_io(d1) (/opt/ruby-enterprise/lib/ruby/1.8/irb/slex.rb:204}
  2.55      0.02        0.00   0.00    0.02      20   RubyLex#token (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:279}
  2.26      0.00        0.00   0.00    0.00     100   Kernel#puts (ruby_runtime:0}
  2.23      0.00        0.00   0.00    0.00      20   Array#& (ruby_runtime:0}
  1.72      0.02        0.00   0.00    0.02       2   RubyLex#lex (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:262}
  1.71      0.02        0.00   0.00    0.02      20   IRB::SLex#match (/opt/ruby-enterprise/lib/ruby/1.8/irb/slex.rb:70}
  1.65      0.00        0.00   0.00    0.00       1   Integer#times (ruby_runtime:0}
  1.60      0.00        0.00   0.00    0.00     163   Fixnum#+ (ruby_runtime:0}
  1.56      0.00        0.00   0.00    0.00     167   Kernel#hash (ruby_runtime:0}
  1.53      0.00        0.00   0.00    0.00     147   Array#empty? (ruby_runtime:0}
  1.24      0.00        0.00   0.00    0.00      20   RubyLex#peek (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:180}
  1.24      0.00        0.00   0.00    0.00      44   <Class::RubyLex>#debug? (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:34}
Rails command line

# USAGE
script/performance/profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]

# EXAMPLE
script/performance/profiler 'Item.all'
Performance Testing:
   Measurement
Benchmark standard
     library
  require 'benchmark'

  puts Benchmark.measure { "a"*1_000_000 }
  # 1.166667   0.050000   1.216667 ( 0.571355)

  n = 50000
  Benchmark.bm   do |x|
    x.report {   for i in 1..n; a = "1"; end }
    x.report {   n.times do   ; a = "1"; end }
    x.report {   1.upto(n) do ; a = "1"; end }
  end

  #       user       system      total         real
  #   1.033333     0.016667   1.016667 (   0.492106)
  #   1.483333     0.000000   1.483333 (   0.694605)
  #   1.516667     0.000000   1.516667 (   0.711077)
Rails command line

# USAGE
script/performance/benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ...

# EXAMPLE
script/performance/benchmarker 10 'Item.all' 'CouchItem.all'
Rails helper methods
            Creating report in your log file

  # Model
  Project.benchmark("Creating project") do
    project = Project.create("name" => "stuff")
    project.create_manager("name" => "David")
    project.milestones << Milestone.find(:all)
  end

  # Controller
  def process_projects
    self.class.benchmark("Processing projects") do
      Project.process(params[:project_ids])
      Project.update_cached_projects
    end
  end

  # View
  <% benchmark("Showing projects partial") do %>
    <%= render :partial => @projects %>
  <% end %>
Performance Test cases
           a special type of integration tests




• script/generate performance_test welcome
• rake test:benchmark (will run 4 times)
• rake test:profile (will run 1 time)
Performance Test cases
       Example
  require 'test_helper'
  require 'performance_test_help'

  class WelcomeTest < ActionController::PerformanceTest
    # Replace this with your real tests.
    def test_homepage
      get '/'
    end
  end
rake test:benchmark
  Started
  BrowsingTest#test_homepage (7 ms warmup)
             wall_time: 2 ms
                memory: 414.53 KB
               objects: 2256
               gc_runs: 0
               gc_time: 0 ms
  .WelcomeTest#test_homepage (4 ms warmup)
             wall_time: 2 ms
                memory: 414.53 KB
               objects: 2256
               gc_runs: 0
               gc_time: 0 ms
  .
  Finished in 0.908874 seconds.

  10 tests, 0 assertions, 0 failures, 0 errors
rake test:profile
 Started
 BrowsingTest#test_homepage (6 ms warmup)
         process_time: 12 ms
               memory: 771.14 KB
              objects: 2653
 .WelcomeTest#test_homepage (4 ms warmup)
         process_time: 12 ms
               memory: 771.14 KB
              objects: 2653
 .
 Finished in 3.49321 seconds.

 6 tests, 0 assertions, 0 failures, 0 errors
Generic Tools
                (black-box)




• httperf
• ab - Apache HTTP server benchmarking tool
How fast can this
server serve requests?
• Use web server to serve static files as
  baseline measurement
• Do not run from the same server (I/O and
  CPU)
• Run from a machine as close as possible
You need know basic
       statistics
• compare not just their means but their
  standard deviations and confidence
  intervals as well.
 • Approximately 68% of the data points lie
    within one standard deviation of the
    mean
 • 95% of the data is within 2 standard
    deviation of the mean
httperf example
httperf --server localhost --port 3000 --uri / --num-conns 10000
httperf --client=0/1 --server=localhost --port=3000 --uri=/ --send-buffer=4096 --recv-buffer=16384 --num-conns=10000 --
num-calls=1

httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 1

Total: connections 10000 requests 10000 replies 10000 test-duration 18.373 s

Connection   rate: 544.3 conn/s (1.8 ms/conn, <=1 concurrent connections)
Connection   time [ms]: min 0.1 avg 1.8 max 4981.7 median 0.5 stddev 50.8
Connection   time [ms]: connect 0.7
Connection   length [replies/conn]: 1.000

Request rate: 544.3 req/s (1.8 ms/req)
Request size [B]: 87.0

Reply   rate [replies/s]: min 55.0 avg 558.3 max 830.7 stddev 436.4 (3 samples)   1 sample need 5s
Reply   time [ms]: response 0.7 transfer 0.4                                      30 samples will be accurate
Reply   size [B]: header 167.0 content 3114.0 footer 0.0 (total 3281.0)
Reply   status: 1xx=0 2xx=10000 3xx=0 4xx=0 5xx=0

CPU time [s]: user 3.24 system 14.09 (user 17.7% system 76.7% total 94.4%)
Net I/O: 1790.1 KB/s (14.7*10^6 bps)

Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Writing Efficient Ruby
        Code
Writing Efficient Ruby
     Code Tips
•   Instance variable faster than accessor
•   Interpolated string faster than + operator
•   In-Place updates
•   Module and class definition scope only execute once
•   Caching Data in Instance or Class Variables
•   Useless .nil?
•   Unnecessary block parameter &block
•   More...
    •   http://www.igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri/
    •   http://ihower.tw/blog/archives/1691
    •   http://en.oreilly.com/rails2009/public/schedule/detail/8680
Interpolated Strings

     s = "#{a} #{b} #{c}"

     # is faster than

     s = a.to_s + b.to_s + c.to_s
In-Place Updates
 Class   Copying   Destructive
 -------------------------------
 String #+         #<<
 String #sub       #sub!
 String #gsub      #gsub!
 Hash    #merge    #merge!
 Array   #+        #concat
 Array   #map      #map!
 Array   #compact #compact!
 Array   #uniq     #uniq!
 Array   #flatten #flatten!
Coding Variable Caching (1)
      def capital_letters
        @capital_lettters ||= ("A".."Z").to_a
      end

      # or

      @@capital_lettters ||= ("A".."Z").to_a
      def capital_letters
        @@capital_lettters
      end
Coding Variable Caching (2)
        def actions
          unless @actions
            # do something expensive
              @actions = expr
          end

          @actions
        end

        # or

        def actions
          @actions ||=
            begin
              # do something expensive
              expr
            end
        end
ActiveSupport::Memoizable

   def total_amount
     # expensive calculate
   end

   def total_income
     # expensive calculate
   end

   def total_expense
     # expensive calculate
   end

   extend ActiveSupport::Memoizable
   memoize :total_amount, :total_income, :total_expense
Method cache
•   Ruby use cached method before method lookup
•   Avoid these methods at runtime, it will clear cache.
    •   def / undef
    •   Module#define_method
    •   Module#remove_method
    •   alias / Module#alias_method
    •   Object#extend
    •   Module#include
    •   public/private/protected/module_function
require 'benchmark'

              class C
                def m; end
              end

              module H
              end

              puts Benchmark.measure {
                  i = 0
                  while i < 100000
                    i+=1
                    l = C.new
                    # l.extend H
                    l.m; l.m; l.m; l.m;
                    l.m; l.m; l.m; l.m;
                  end
              }



Example from “What Makes Ruby Go? An Implementation Primer (RailsConf 2009)”
require 'benchmark'

class C
  def m; end
end

module H
end

puts Benchmark.measure {
    i = 0
    while i < 100000
      i+=1
      l = C.new
      l.extend H
      l.m; l.m; l.m; l.m;
      l.m; l.m; l.m; l.m;
    end
}
require 'benchmark'

class C
  def m; end
end

module H
end

puts Benchmark.measure {
    i = 0
    x = C.new
    while i < 100000
      i+=1
      l = C.new
      x.extend H # Extend on an unrelated object!
      l.m; l.m; l.m; l.m;
      l.m; l.m; l.m; l.m;
    end
}
require 'benchmark'

class C
  def m; end
end

module H
end

class MyC < C
  include H
end

puts Benchmark.measure {
    i = 0
    while i < 100000
      i+=1
      l = MyC.new
      l.m; l.m; l.m; l.m;
      l.m; l.m; l.m; l.m;
    end
}
milliseconds
         no extend (243ms)


           extend (1536ms)


extend an unrelated (316ms)


            include (252ms)

                              0   500   1000   1500   2000




                                                                       (MacBook Pro 2.2G)
Constant Caching


• Don’t redefined constants at runtime
• Don’t define new constants frequently
Use Ruby Enterprise
Edition (REE) or Ruby 1.9
Ruby is slow?
• Language Micro-benchmarks !=
  performance in complex systems
• Other factors:
 • application architecture
 • the ability to leverage higher-level
    (Simplify things which may be complex to implement in other languages.
    => No code is faster than no code.)


  • Rails is faster than many PHP frameworks
    http://avnetlabs.com/php/php-framework-comparison-benchmarks
Use faster Ruby Library
                         C Extension++

• XML parser
  http://nokogiri.org/


• JSON parser
  http://github.com/brianmario/yajl-ruby/


• CSV parser
  http://www.toastyapps.com/excelsior/


• HTTP client
  http://github.com/pauldix/typhoeus


• Date
  http://github.com/rtomayko/date-performance
Caching
About Caching

• Ugly if you cache everywhere
• More bugs and tough to debug
  includeing stale, data, inconsistent data, timing-based bugs.


• Complicated: expire, security
• Limit your user interface options
Cache Store
ActionController::Base.cache_store = :mem_cache_store, "localhost"
ActionController::Base.cache_store = :compressed_mem_cache_store, "localhost"

ActionController::Base.cache_store = :memory_store
ActionController::Base.cache_store = :synchronized_memory_store

ActionController::Base.cache_store = :file_store, "/path/to/cache/directory"
ActionController::Base.cache_store = :drb_store, "druby://localhost:9192"
View Caching

• Page Caching
• Action Caching
• Fragment Caching
Page Caching

class ProductsController < ActionController

  caches_page :index

  def index; end

end
Action Caching
class ProductsController < ActionController

  before_filter :authenticate, :only => [ :edit, :create ]
  caches_action :edit

  def index; end

  def create
    expire_page :action => :index
    expire_action :action => :edit
  end

  def edit; end

end
Fragment Caching

<% cache(:key =>
  ['all_available_products', @latest_product.created_at].join(':')) do %>
  All available products:
<% end %>

expire_fragment(:key =>
  ['all_available_products', @latest_product.created_at].join(':'))
Sweepers
class StoreSweeper < ActionController::Caching::Sweeper
  # This sweeper is going to keep an eye on the Product model
  observe Product

  # If our sweeper detects that a Product was created call this
  def after_create(product)
          expire_cache_for(product)
  end

  # If our sweeper detects that a Product was updated call this
  def after_update(product)
          expire_cache_for(product)
  end

  # If our sweeper detects that a Product was deleted call this
  def after_destroy(product)
          expire_cache_for(product)
  end

  private
  def expire_cache_for(record)
    # Expire the list page now that we added a new product
    expire_page(:controller => '#{record}', :action => 'list')

    # Expire a fragment
    expire_fragment(:controller => '#{record}',
      :action => 'recent', :action_suffix => 'all_products')
  end
end
Caching yourself

Rails.cache.read("city")   # => nil
Rails.cache.write("city", "Duckburgh")
Rails.cache.read("city")   # => "Duckburgh"

Rails.cache.fetch("#{id}-data") do
    Book.sum(:amount, :conditions => { :category_id => self.category_ids } )
end
Use Memcached
• Free & open source, high-performance,
  distributed memory object caching system
• an in-memory key-value store for small
  chunks of arbitrary data (strings, objects)
  from results of database calls, API calls, or
  page rendering.
Memcached
• Key: 256 characters
• Data: 1mb
• SET/ADD/REPLACE/GET operators
• NOT persistent data store
• caching “noreply” principle
Caching secret


• Key naming
• Expiration
Caching Expire
• expire it after create/update/delete
 • race condition? lock it first.
• reset it after update
 • race condition first time? lock it first.
• set expire time
 • race condition? proactive cache refill
Using memcached
SQL and ActiveRecord
ORM is a high-level library that it’s easy to forget about
        efficiency until it becomes a problem.
http://www.engineyard.com/blog/2009/thats-not-a-memory-leak-its-bloat/
N+1 Queries
# model
class User < ActieRecord::Base
    has_one :car
end

class Car < ActiveRecord::Base
    belongs_to :user
end

# your controller
def index
  @users = User.paginate( :page => params[:page], :per_page => 20 )
end

# view
<% @users.each do |user| %>
   <%= user.car.name %>
<% end %>
Add :include

# your controller
def index
  @users = User.paginate( :include => :car, :page => params
[:page], :per_page => 20 )
end
Bullet plugin
• http://github.com/flyerhzm/bullet
  Help you reduce the number of queries
  with alerts (and growl).
Missing indexing
• Foreign key indexs
• Columns that need to be sorted
• Lookup fields
• Columns that are used in a GROUP BY
• http://github.com/eladmeidar/rails_indexes
  Rake tasks to find missing indexes.
Only select you need
     Event.find(:all, :select => "id, title, description")

     class User < ActiveRecord::Base
         named_scope :short, :select => "id, name, email"
     end

     User.short.find(:all)




• http://github.com/methodmissing/scrooge
  SQL query optimizer, so you query for only
  what your page needs.
Replace :include to :join
    for some case
Group.find(:all, :include => [ :group_memberships ], :conditions =>
[ "group_memberships.created_at > ?", Time.now - 30.days ] )

# you can replace :include to :join

Group.find(:all, :joins => [ :group_memberships ], :conditions =>
[ "group_memberships.created_at > ?", Time.now - 30.days ] )
Batch finding
Article.find_each do |a|
    # iterate over all articles, in chunks of 1000 (the default)
end

Article.find_each(:conditions => { :published => true }, :batch_size => 100 ) do |a|
  # iterate over published articles in chunks of 100
end

Article.find_in_batches do |articles|
    articles.each do |a|
      # articles is array of size 1000
    end
end

Article.find_in_batches(batch_size => 100 ) do |articles|
    articles.each do |a|
      # iterate over all articles in chunks of 100
    end
end
Transaction for group
     operations
     my_collection.each do |q|
         Quote.create({:phrase => q})
     end

     # Add transaction
     Quote.transaction do
      my_collection.each do |q|
         Quote.create({:phrase => q})
      end
     end
SQL query planner
• EXPLAIN keyword
• http://github.com/dsboulder/query_reviewer
SQL best practices
Use Full-text search
        engine

• Sphinx and thinking_sphinx plugin
• Ferret gem and acts_as_ferret
Use Constant for
  domain data
   class Rating < ActiveRecord::Base

         G = Rating.find_by_name('G')
         PG = Rating.find_by_name('PG')
         R = Rating.find_by_name('R')
         #....

   end

   Rating::G
   Rating::PG
   Rating::R
Counter cache
class Topic < ActiveRecord::Base
    has_many :posts
end

class Posts < ActiveRecord::Base
    belongs_to :topic, :counter_cache => true
end

@topic.posts.size
Store Your Reports


• Aggregate reports via cron and rake
AR Caching Plugins

• http://github.com/nkallen/cache-money
• http://github.com/fauna/interlock
• http://github.com/defunkt/cache_fu
• Need careful to go to these solution,
  because it’s very intrusive.
Consider
         NoSQL data store

• Key-value stores for high performance
  Redis, Tokyo Cabinet, Flare


• Document stores for huge storage
  MongoDB, CouchDB


• Record store for high scalability and availability
  Cassandra, HBase,Voldemort
Use key-value store
      from now

• Redis, Tokyo Cabinet are very very fast
• Avoid touching the RDBMS when storing
  non-critical data, hit count, download
  count, online users count...etc
Moneta

• a unified interface to key/value stores
• http://github.com/wycats/moneta/tree
moneta supports:
•   File store for
                          • S3
    xattr
•   Basic File Store      • Berkeley DB
•   Memcache store        • Redis
•   In-memory store
                          • SDBM
•   The xattrs in a file
                          • Tokyo
    system
•   DataMapper            • CouchDB
moneta API:
•   #[](key)
•   #[]=(key, value)
•   #delete(key)
•   #key?(key)
•   #store(key, value, options)
•   #update_key(key, options):
•   #clear
example
begin
  # for   developer has tokyo cabinet
  STORE   = Moneta::Tyrant.new( :host => 'localhost', :port => 1978 )
rescue
  # for   developer has not tokyo cabinet
  STORE   = Moneta::BasicFile.new( :path => "tmp" )
end

STORE["mykey"] = { :foo => 111 , :bar => 222 }
Rails Metal
               a subset of Rack middleware




• 2~3x faster than a controller, because it
  bypasses routes and controller.
• APIs and anything which need not
  ActionView
Use web server or
   CDN for static file

• Web server is 10x faster than your
  application server
• Set :x_sendfile to true if you use Apache
  mod_xsendfile or Lighttpd
Web performance
    client-side analysis

• http://developer.yahoo.com/yslow/
• http://code.google.com/speed/page-speed/
Web performance
             Rules 14
•   Make Fewer HTTP Requests     •   Make JavaScript and CSS
                                     External
•   Use a Content Delivery
    Network                      •   Reduce DNS Lookups

•   Add an Expires Header        •   Minify JavaScript

•   Gzip Components              •   Avoid Redirects

•   Put Stylesheets at the Top   •   Remove Duplicates Scripts

•   Put Scripts at the Bottom    •   Configure ETags

•   Avoid CSS Expressions        •   Make Ajax Cacheable
Use external programs

 def thumbnail(temp, target)
     system("/usr/local/bin/convert #{escape(temp)} -resize
 48x48! #{escape(target}")
 end
Write inline C/C++ code
• RubyInline: Write foreign code within ruby code
  http://rubyinline.rubyforge.org/RubyInline/


• Rice: Ruby Interface for C++ Extensions
  http://rice.rubyforge.org/


• Ruby-FFI: a ruby extension for programmatically
  loading dynamic libraries
  http://github.com/ffi/ffi
Reference
•   Advanced Rails Chap.6 Performance (O’Reilly)
•   Rails Rescue Handbook
•   Writing Efficient Ruby Code (Addison-Wesley)
•   Ruby on Rails Code Review (Peepcode)
•   Rails 2 Chap. 13 Security and Performance Enhancements (friendsof)
•   Deploying Rails Application Chap.9 Performance (Pragmatic)
•   http://guides.rubyonrails.org/caching_with_rails.html
•   http://guides.rubyonrails.org/performance_testing.html
•   http://railslab.newrelic.com/scaling-rails
•   http://antoniocangiano.com/2007/02/10/top-10-ruby-on-rails-performance-tips/
•   http://www.engineyard.com/blog/2009/thats-not-a-memory-leak-its-bloat/
•   http://jstorimer.com/ruby/2009/12/13/essential-rails-plugins-for-your-inner-dba.html
•   http://asciicasts.com/episodes/161-three-profiling-tools
•   http://robots.thoughtbot.com/post/163627511/a-grand-piano-for-your-violin
So, how to scale?
• Rails performance (AR...etc how to ruby code)
• Web performance (yslow related)
• Asynchrony Processing (Message queue)
• HTTP Reverse Proxy Caching
• Partition Component using SOA
• Distributed Filesystem/Database
TODO (maybe next time)

• NoSQL: Key-value data store
• Front-end web performance
• HTTP reverse proxy caching
The End

More Related Content

What's hot

Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryMauro Rocco
 
Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표
Kwen Won Lee
 
Atomicity In Redis: Thomas Hunter
Atomicity In Redis: Thomas HunterAtomicity In Redis: Thomas Hunter
Atomicity In Redis: Thomas Hunter
Redis Labs
 
MySQL 상태 메시지 분석 및 활용
MySQL 상태 메시지 분석 및 활용MySQL 상태 메시지 분석 및 활용
MySQL 상태 메시지 분석 및 활용
I Goo Lee
 
Iocp advanced
Iocp advancedIocp advanced
Iocp advanced
Nam Hyeonuk
 
Building Advanced XSS Vectors
Building Advanced XSS VectorsBuilding Advanced XSS Vectors
Building Advanced XSS Vectors
Rodolfo Assis (Brute)
 
FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들
Taegon Kim
 
Ejercicios LDAP
Ejercicios LDAPEjercicios LDAP
Ejercicios LDAP
OpenCourseWare México
 
NLU Tech Talk with KorBERT
NLU Tech Talk with KorBERTNLU Tech Talk with KorBERT
NLU Tech Talk with KorBERT
LGCNSairesearch
 
Advanced nGrinder 2nd Edition
Advanced nGrinder 2nd EditionAdvanced nGrinder 2nd Edition
Advanced nGrinder 2nd Edition
JunHo Yoon
 
Velocity 2015 linux perf tools
Velocity 2015 linux perf toolsVelocity 2015 linux perf tools
Velocity 2015 linux perf tools
Brendan Gregg
 
JS Event Loop
JS Event LoopJS Event Loop
JS Event Loop
Saai Vignesh P
 
쉽고 강력한 모바일 백엔드 Parse-server
쉽고 강력한 모바일 백엔드 Parse-server쉽고 강력한 모바일 백엔드 Parse-server
쉽고 강력한 모바일 백엔드 Parse-server
InGrowth Gim
 
Iocp 기본 구조 이해
Iocp 기본 구조 이해Iocp 기본 구조 이해
Iocp 기본 구조 이해
Nam Hyeonuk
 
Bug bounty recon.pdf
Bug bounty recon.pdfBug bounty recon.pdf
Bug bounty recon.pdf
EusebiuDanielBlindu
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
Bryan Helmig
 
How to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor NettyHow to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor Netty
VMware Tanzu
 
Database Firewall with Snort
Database Firewall with SnortDatabase Firewall with Snort
Database Firewall with Snort
Narudom Roongsiriwong, CISSP
 
Obscure Go Optimisations
Obscure Go OptimisationsObscure Go Optimisations
Obscure Go Optimisations
Bryan Boreham
 

What's hot (20)

Ruby
RubyRuby
Ruby
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & Celery
 
Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표Overlapped IO와 IOCP 조사 발표
Overlapped IO와 IOCP 조사 발표
 
Atomicity In Redis: Thomas Hunter
Atomicity In Redis: Thomas HunterAtomicity In Redis: Thomas Hunter
Atomicity In Redis: Thomas Hunter
 
MySQL 상태 메시지 분석 및 활용
MySQL 상태 메시지 분석 및 활용MySQL 상태 메시지 분석 및 활용
MySQL 상태 메시지 분석 및 활용
 
Iocp advanced
Iocp advancedIocp advanced
Iocp advanced
 
Building Advanced XSS Vectors
Building Advanced XSS VectorsBuilding Advanced XSS Vectors
Building Advanced XSS Vectors
 
FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들FE로 취업 전에 알았으면 좋았을 것들
FE로 취업 전에 알았으면 좋았을 것들
 
Ejercicios LDAP
Ejercicios LDAPEjercicios LDAP
Ejercicios LDAP
 
NLU Tech Talk with KorBERT
NLU Tech Talk with KorBERTNLU Tech Talk with KorBERT
NLU Tech Talk with KorBERT
 
Advanced nGrinder 2nd Edition
Advanced nGrinder 2nd EditionAdvanced nGrinder 2nd Edition
Advanced nGrinder 2nd Edition
 
Velocity 2015 linux perf tools
Velocity 2015 linux perf toolsVelocity 2015 linux perf tools
Velocity 2015 linux perf tools
 
JS Event Loop
JS Event LoopJS Event Loop
JS Event Loop
 
쉽고 강력한 모바일 백엔드 Parse-server
쉽고 강력한 모바일 백엔드 Parse-server쉽고 강력한 모바일 백엔드 Parse-server
쉽고 강력한 모바일 백엔드 Parse-server
 
Iocp 기본 구조 이해
Iocp 기본 구조 이해Iocp 기본 구조 이해
Iocp 기본 구조 이해
 
Bug bounty recon.pdf
Bug bounty recon.pdfBug bounty recon.pdf
Bug bounty recon.pdf
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
 
How to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor NettyHow to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor Netty
 
Database Firewall with Snort
Database Firewall with SnortDatabase Firewall with Snort
Database Firewall with Snort
 
Obscure Go Optimisations
Obscure Go OptimisationsObscure Go Optimisations
Obscure Go Optimisations
 

Viewers also liked

ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2
RORLAB
 
ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1
RORLAB
 
Make your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On RailsMake your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On Rails
Nataly Tkachuk
 
6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend
Forrest Chang
 
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
Paul Gallagher
 
Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)
Neev Technologies
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
Agnieszka Figiel
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
Aizat Faiz
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and RailsWen-Tien Chang
 
Ruby Beyond Rails
Ruby Beyond RailsRuby Beyond Rails
Ruby Beyond Rails
Gaveen Prabhasara
 
From a monolithic Ruby on Rails app to the JVM
From a monolithic  Ruby on Rails app  to the JVMFrom a monolithic  Ruby on Rails app  to the JVM
From a monolithic Ruby on Rails app to the JVMPhil Calçado
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
Thomas Fuchs
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017
John Maeda
 

Viewers also liked (14)

Rails Security
Rails SecurityRails Security
Rails Security
 
ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2
 
ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1
 
Make your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On RailsMake your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On Rails
 
6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend
 
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
 
Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and Rails
 
Ruby Beyond Rails
Ruby Beyond RailsRuby Beyond Rails
Ruby Beyond Rails
 
From a monolithic Ruby on Rails app to the JVM
From a monolithic  Ruby on Rails app  to the JVMFrom a monolithic  Ruby on Rails app  to the JVM
From a monolithic Ruby on Rails app to the JVM
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017
 

Similar to Rails Performance

Run Node Run
Run Node RunRun Node Run
Run Node Run
Kevin Swiber
 
Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009
pratiknaik
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performance
Engine Yard
 
The Architecture of PicCollage Server
The Architecture of PicCollage ServerThe Architecture of PicCollage Server
The Architecture of PicCollage ServerLin Jen-Shin
 
Ruby on Rails workshop for beginner
Ruby on Rails workshop for beginnerRuby on Rails workshop for beginner
Ruby on Rails workshop for beginner
Umair Amjad
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
Hiroshi SHIBATA
 
DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜
DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜
DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜
Michitoshi Yoshida
 
Performance & Scalability Improvements in Perforce
Performance & Scalability Improvements in PerforcePerformance & Scalability Improvements in Perforce
Performance & Scalability Improvements in Perforce
Perforce
 
Rack
RackRack
Rack
shaokun
 
Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?
Felix Geisendörfer
 
Jasig rubyon rails
Jasig rubyon railsJasig rubyon rails
Jasig rubyon rails_zaMmer_
 
Jasig rubyon rails
Jasig rubyon railsJasig rubyon rails
Jasig rubyon rails_zaMmer_
 
mtl_rubykaigi
mtl_rubykaigimtl_rubykaigi
mtl_rubykaigi
Hirotomo Oi
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
orkaplan
 
Typesafe spark- Zalando meetup
Typesafe spark- Zalando meetupTypesafe spark- Zalando meetup
Typesafe spark- Zalando meetup
Stavros Kontopoulos
 
Speedy TDD with Rails
Speedy TDD with RailsSpeedy TDD with Rails
Speedy TDD with Rails
PatchSpace Ltd
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Masahiro Nagano
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
Hiroshi SHIBATA
 
Ruby projects of interest for DevOps
Ruby projects of interest for DevOpsRuby projects of interest for DevOps
Ruby projects of interest for DevOpsRicardo Sanchez
 

Similar to Rails Performance (20)

Run Node Run
Run Node RunRun Node Run
Run Node Run
 
Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performance
 
The Architecture of PicCollage Server
The Architecture of PicCollage ServerThe Architecture of PicCollage Server
The Architecture of PicCollage Server
 
Ruby on Rails workshop for beginner
Ruby on Rails workshop for beginnerRuby on Rails workshop for beginner
Ruby on Rails workshop for beginner
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜
DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜
DBA だってもっと効率化したい!〜最近の自動化事情とOracle Database〜
 
Performance & Scalability Improvements in Perforce
Performance & Scalability Improvements in PerforcePerformance & Scalability Improvements in Perforce
Performance & Scalability Improvements in Perforce
 
Rack
RackRack
Rack
 
Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?
 
Jasig rubyon rails
Jasig rubyon railsJasig rubyon rails
Jasig rubyon rails
 
Jasig rubyon rails
Jasig rubyon railsJasig rubyon rails
Jasig rubyon rails
 
mtl_rubykaigi
mtl_rubykaigimtl_rubykaigi
mtl_rubykaigi
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
 
Typesafe spark- Zalando meetup
Typesafe spark- Zalando meetupTypesafe spark- Zalando meetup
Typesafe spark- Zalando meetup
 
Speedy TDD with Rails
Speedy TDD with RailsSpeedy TDD with Rails
Speedy TDD with Rails
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
 
Ruby projects of interest for DevOps
Ruby projects of interest for DevOpsRuby projects of interest for DevOps
Ruby projects of interest for DevOps
 

More from Wen-Tien Chang

⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨
Wen-Tien Chang
 
Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛
Wen-Tien Chang
 
A brief introduction to Machine Learning
A brief introduction to Machine LearningA brief introduction to Machine Learning
A brief introduction to Machine Learning
Wen-Tien Chang
 
淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2
Wen-Tien Chang
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails Tutorial
Wen-Tien Chang
 
RSpec & TDD Tutorial
RSpec & TDD TutorialRSpec & TDD Tutorial
RSpec & TDD Tutorial
Wen-Tien Chang
 
ALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborate
Wen-Tien Chang
 
Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀Wen-Tien Chang
 
Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)Wen-Tien Chang
 
Exception Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in RubyException Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in RubyWen-Tien Chang
 
從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事Wen-Tien Chang
 
Yet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom upYet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom upWen-Tien Chang
 
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩Wen-Tien Chang
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Wen-Tien Chang
 
A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0
Wen-Tien Chang
 
RubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingRubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & Closing
Wen-Tien Chang
 
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean StartupWen-Tien Chang
 
那些 Functional Programming 教我的事
那些 Functional Programming 教我的事那些 Functional Programming 教我的事
那些 Functional Programming 教我的事
Wen-Tien Chang
 
RubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & ClosingRubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & ClosingWen-Tien Chang
 

More from Wen-Tien Chang (20)

⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨
 
Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛Ruby Rails 老司機帶飛
Ruby Rails 老司機帶飛
 
A brief introduction to Machine Learning
A brief introduction to Machine LearningA brief introduction to Machine Learning
A brief introduction to Machine Learning
 
淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails Tutorial
 
RSpec & TDD Tutorial
RSpec & TDD TutorialRSpec & TDD Tutorial
RSpec & TDD Tutorial
 
ALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborate
 
Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀Git 版本控制系統 -- 從微觀到宏觀
Git 版本控制系統 -- 從微觀到宏觀
 
Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby (with presentation note)
 
Exception Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in RubyException Handling: Designing Robust Software in Ruby
Exception Handling: Designing Robust Software in Ruby
 
從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事從 Classes 到 Objects: 那些 OOP 教我的事
從 Classes 到 Objects: 那些 OOP 教我的事
 
Yet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom upYet another introduction to Git - from the bottom up
Yet another introduction to Git - from the bottom up
 
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介
 
A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0A brief introduction to SPDY - 邁向 HTTP/2.0
A brief introduction to SPDY - 邁向 HTTP/2.0
 
RubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingRubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & Closing
 
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
 
Git Tutorial 教學
Git Tutorial 教學Git Tutorial 教學
Git Tutorial 教學
 
那些 Functional Programming 教我的事
那些 Functional Programming 教我的事那些 Functional Programming 教我的事
那些 Functional Programming 教我的事
 
RubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & ClosingRubyConf Taiwan 2011 Opening & Closing
RubyConf Taiwan 2011 Opening & Closing
 

Recently uploaded

A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..
UiPathCommunity
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 

Recently uploaded (20)

A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..UiPath Community Day Dubai: AI at Work..
UiPath Community Day Dubai: AI at Work..
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 

Rails Performance

  • 1. Rails Performance Best Practices http://ihower.tw 2010/3
  • 2. About Me • a.k.a. ihower • http://ihower.tw • http://twitter.com/ihower • http://github.com/ihower • Ruby on Rails Developer since 2006 • Ruby Taiwan Community • http://ruby.tw
  • 3. Performance Worse Practices • Premature Optimization • Guessing • Caching everything • Fighting the framework
  • 4. Performance Guidelines • Algorithmic improvements always beat code tweaks • As a general rule, maintainability beats performance • Only optimize what matters (80/20 rule) • Measure twice, cut once • Must be balanced with flexibility
  • 5. How to improve performance? • Find the target baseline • Know where you are now • Profile to find bottlenecks • Remove bottlenecks • Repeat
  • 6. Agenda • Analysis and Measurement • Write Efficient Ruby code • Use REE 1.8.7 or Ruby 1.9 • Use faster Ruby Library • Caching • SQL and ActiveRecord • Consider NoSQL storage • Rack and Rails Metal • Use HTTP server for static files • Front-end web performance • Use external programs or write inline C code
  • 8. Server Log Analysis • http://github.com/wvanbergen/request-log-analyzer • Request distribution per hour • Most requested • HTTP methods • HTTP statuses returned • Rails action cache hits • Request duration • View rendering time • Database time • Process blockers • Failed requests
  • 9. Commercial Monitor Products • New Relic • Scout
  • 10. Rack::Bug Rails middleware which gives you an informative toolbar in your browser
  • 11.
  • 12. MemoryLogic Adds in proccess id and memory usage in your rails logs, great for tracking down memory leaks • http://github.com/binarylogic/memorylogic Processing WelcomeController#index (for 127.0.0.1 at 2010-02-26 01:51:54) [GET] (mem 104792) Parameters: {"action"=>"index", "controller"=>"welcome"} (mem 104792) ... Memory usage: 108888 | PID: 6170 (mem 108888) Completed in 3570ms (View: 1861, DB: 1659) | 200 OK [http://localhost/] (mem 108888)
  • 13. oink Log parser to identify actions which significantly increase VM heap size • http://github.com/noahd1/oink script/oink -t 0 ~/rails-app/log/development.log ---- MEMORY THRESHOLD ---- THRESHOLD: 0 MB -- SUMMARY -- Worst Requests: 1. Feb 26 02:12:45, 37360 KB, SessionsController#new 2. Feb 26 02:12:41, 37352 KB, BooksController#hot 3. Feb 26 02:12:21, 16824 KB, BooksController#hot 4. Feb 26 02:12:25, 11632 KB, BooksController#hot 5. Feb 26 02:12:19, 11120 KB, BooksController#hot 6. Feb 26 02:12:51, 9888 KB, WelcomeController#index 7. Feb 26 02:12:28, 7548 KB, WelcomeController#index 8. Feb 26 02:12:23, 5120 KB, ArticlesController#index Worst Actions: 4, BooksController#hot 2, WelcomeController#index 1, ArticlesController#index 1, SessionsController#new
  • 14. ruby-prof gem • a fast code profiler for Ruby. Its features include: • Speed - it is a C extension • Modes - call times, memory usage and object allocations. • Reports - can generate text and cross-referenced html reports • Threads - supports profiling multiple threads simultaneously • Recursive calls - supports profiling recursive method calls
  • 15. ruby-prof example (1) require 'ruby-prof' # Profile the code RubyProf.start ... # code to profile 100.times { puts "blah" } result = RubyProf.stop # Print a flat profile to text printer = RubyProf::FlatPrinter.new(result) printer.print(STDOUT, 0)
  • 16. ruby-prof example (2) Thread ID: 2148368700 Total: 0.022092 %self total self wait child calls name 13.19 0.00 0.00 0.00 0.00 2 Readline#readline (ruby_runtime:0} 12.16 0.01 0.00 0.00 0.00 79 RubyLex#getc (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:101} 4.87 0.00 0.00 0.00 0.00 30 RubyLex#ungetc (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:144} 4.52 0.00 0.00 0.00 0.00 5 RubyLex#identify_identifier (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:770} 4.41 0.00 0.00 0.00 0.00 202 IO#write (ruby_runtime:0} 4.03 0.02 0.00 0.00 0.02 20 IRB::SLex::Node#match_io (/opt/ruby-enterprise/lib/ruby/1.8/irb/slex.rb:204} 4.00 0.01 0.00 0.00 0.01 28 Proc#call (ruby_runtime:0} 2.92 0.00 0.00 0.00 0.00 20 RubyToken#Token (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-token.rb:84} 2.85 0.00 0.00 0.00 0.00 271 String#== (ruby_runtime:0} 2.65 0.01 0.00 0.00 0.01 14 IRB::SLex::Node#match_io(d1) (/opt/ruby-enterprise/lib/ruby/1.8/irb/slex.rb:204} 2.55 0.02 0.00 0.00 0.02 20 RubyLex#token (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:279} 2.26 0.00 0.00 0.00 0.00 100 Kernel#puts (ruby_runtime:0} 2.23 0.00 0.00 0.00 0.00 20 Array#& (ruby_runtime:0} 1.72 0.02 0.00 0.00 0.02 2 RubyLex#lex (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:262} 1.71 0.02 0.00 0.00 0.02 20 IRB::SLex#match (/opt/ruby-enterprise/lib/ruby/1.8/irb/slex.rb:70} 1.65 0.00 0.00 0.00 0.00 1 Integer#times (ruby_runtime:0} 1.60 0.00 0.00 0.00 0.00 163 Fixnum#+ (ruby_runtime:0} 1.56 0.00 0.00 0.00 0.00 167 Kernel#hash (ruby_runtime:0} 1.53 0.00 0.00 0.00 0.00 147 Array#empty? (ruby_runtime:0} 1.24 0.00 0.00 0.00 0.00 20 RubyLex#peek (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:180} 1.24 0.00 0.00 0.00 0.00 44 <Class::RubyLex>#debug? (/opt/ruby-enterprise/lib/ruby/1.8/irb/ruby-lex.rb:34}
  • 17. Rails command line # USAGE script/performance/profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html] # EXAMPLE script/performance/profiler 'Item.all'
  • 18. Performance Testing: Measurement
  • 19. Benchmark standard library require 'benchmark' puts Benchmark.measure { "a"*1_000_000 } # 1.166667 0.050000 1.216667 ( 0.571355) n = 50000 Benchmark.bm do |x| x.report { for i in 1..n; a = "1"; end } x.report { n.times do ; a = "1"; end } x.report { 1.upto(n) do ; a = "1"; end } end # user system total real # 1.033333 0.016667 1.016667 ( 0.492106) # 1.483333 0.000000 1.483333 ( 0.694605) # 1.516667 0.000000 1.516667 ( 0.711077)
  • 20. Rails command line # USAGE script/performance/benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ... # EXAMPLE script/performance/benchmarker 10 'Item.all' 'CouchItem.all'
  • 21. Rails helper methods Creating report in your log file # Model Project.benchmark("Creating project") do project = Project.create("name" => "stuff") project.create_manager("name" => "David") project.milestones << Milestone.find(:all) end # Controller def process_projects self.class.benchmark("Processing projects") do Project.process(params[:project_ids]) Project.update_cached_projects end end # View <% benchmark("Showing projects partial") do %> <%= render :partial => @projects %> <% end %>
  • 22. Performance Test cases a special type of integration tests • script/generate performance_test welcome • rake test:benchmark (will run 4 times) • rake test:profile (will run 1 time)
  • 23. Performance Test cases Example require 'test_helper' require 'performance_test_help' class WelcomeTest < ActionController::PerformanceTest # Replace this with your real tests. def test_homepage get '/' end end
  • 24. rake test:benchmark Started BrowsingTest#test_homepage (7 ms warmup) wall_time: 2 ms memory: 414.53 KB objects: 2256 gc_runs: 0 gc_time: 0 ms .WelcomeTest#test_homepage (4 ms warmup) wall_time: 2 ms memory: 414.53 KB objects: 2256 gc_runs: 0 gc_time: 0 ms . Finished in 0.908874 seconds. 10 tests, 0 assertions, 0 failures, 0 errors
  • 25. rake test:profile Started BrowsingTest#test_homepage (6 ms warmup) process_time: 12 ms memory: 771.14 KB objects: 2653 .WelcomeTest#test_homepage (4 ms warmup) process_time: 12 ms memory: 771.14 KB objects: 2653 . Finished in 3.49321 seconds. 6 tests, 0 assertions, 0 failures, 0 errors
  • 26. Generic Tools (black-box) • httperf • ab - Apache HTTP server benchmarking tool
  • 27. How fast can this server serve requests? • Use web server to serve static files as baseline measurement • Do not run from the same server (I/O and CPU) • Run from a machine as close as possible
  • 28. You need know basic statistics • compare not just their means but their standard deviations and confidence intervals as well. • Approximately 68% of the data points lie within one standard deviation of the mean • 95% of the data is within 2 standard deviation of the mean
  • 29. httperf example httperf --server localhost --port 3000 --uri / --num-conns 10000 httperf --client=0/1 --server=localhost --port=3000 --uri=/ --send-buffer=4096 --recv-buffer=16384 --num-conns=10000 -- num-calls=1 httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE Maximum connect burst length: 1 Total: connections 10000 requests 10000 replies 10000 test-duration 18.373 s Connection rate: 544.3 conn/s (1.8 ms/conn, <=1 concurrent connections) Connection time [ms]: min 0.1 avg 1.8 max 4981.7 median 0.5 stddev 50.8 Connection time [ms]: connect 0.7 Connection length [replies/conn]: 1.000 Request rate: 544.3 req/s (1.8 ms/req) Request size [B]: 87.0 Reply rate [replies/s]: min 55.0 avg 558.3 max 830.7 stddev 436.4 (3 samples) 1 sample need 5s Reply time [ms]: response 0.7 transfer 0.4 30 samples will be accurate Reply size [B]: header 167.0 content 3114.0 footer 0.0 (total 3281.0) Reply status: 1xx=0 2xx=10000 3xx=0 4xx=0 5xx=0 CPU time [s]: user 3.24 system 14.09 (user 17.7% system 76.7% total 94.4%) Net I/O: 1790.1 KB/s (14.7*10^6 bps) Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
  • 31. Writing Efficient Ruby Code Tips • Instance variable faster than accessor • Interpolated string faster than + operator • In-Place updates • Module and class definition scope only execute once • Caching Data in Instance or Class Variables • Useless .nil? • Unnecessary block parameter &block • More... • http://www.igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri/ • http://ihower.tw/blog/archives/1691 • http://en.oreilly.com/rails2009/public/schedule/detail/8680
  • 32. Interpolated Strings s = "#{a} #{b} #{c}" # is faster than s = a.to_s + b.to_s + c.to_s
  • 33. In-Place Updates Class Copying Destructive ------------------------------- String #+ #<< String #sub #sub! String #gsub #gsub! Hash #merge #merge! Array #+ #concat Array #map #map! Array #compact #compact! Array #uniq #uniq! Array #flatten #flatten!
  • 34. Coding Variable Caching (1) def capital_letters @capital_lettters ||= ("A".."Z").to_a end # or @@capital_lettters ||= ("A".."Z").to_a def capital_letters @@capital_lettters end
  • 35. Coding Variable Caching (2) def actions unless @actions # do something expensive @actions = expr end @actions end # or def actions @actions ||= begin # do something expensive expr end end
  • 36. ActiveSupport::Memoizable def total_amount # expensive calculate end def total_income # expensive calculate end def total_expense # expensive calculate end extend ActiveSupport::Memoizable memoize :total_amount, :total_income, :total_expense
  • 37. Method cache • Ruby use cached method before method lookup • Avoid these methods at runtime, it will clear cache. • def / undef • Module#define_method • Module#remove_method • alias / Module#alias_method • Object#extend • Module#include • public/private/protected/module_function
  • 38. require 'benchmark' class C def m; end end module H end puts Benchmark.measure { i = 0 while i < 100000 i+=1 l = C.new # l.extend H l.m; l.m; l.m; l.m; l.m; l.m; l.m; l.m; end } Example from “What Makes Ruby Go? An Implementation Primer (RailsConf 2009)”
  • 39. require 'benchmark' class C def m; end end module H end puts Benchmark.measure { i = 0 while i < 100000 i+=1 l = C.new l.extend H l.m; l.m; l.m; l.m; l.m; l.m; l.m; l.m; end }
  • 40. require 'benchmark' class C def m; end end module H end puts Benchmark.measure { i = 0 x = C.new while i < 100000 i+=1 l = C.new x.extend H # Extend on an unrelated object! l.m; l.m; l.m; l.m; l.m; l.m; l.m; l.m; end }
  • 41. require 'benchmark' class C def m; end end module H end class MyC < C include H end puts Benchmark.measure { i = 0 while i < 100000 i+=1 l = MyC.new l.m; l.m; l.m; l.m; l.m; l.m; l.m; l.m; end }
  • 42. milliseconds no extend (243ms) extend (1536ms) extend an unrelated (316ms) include (252ms) 0 500 1000 1500 2000 (MacBook Pro 2.2G)
  • 43. Constant Caching • Don’t redefined constants at runtime • Don’t define new constants frequently
  • 44. Use Ruby Enterprise Edition (REE) or Ruby 1.9
  • 45. Ruby is slow? • Language Micro-benchmarks != performance in complex systems • Other factors: • application architecture • the ability to leverage higher-level (Simplify things which may be complex to implement in other languages. => No code is faster than no code.) • Rails is faster than many PHP frameworks http://avnetlabs.com/php/php-framework-comparison-benchmarks
  • 46. Use faster Ruby Library C Extension++ • XML parser http://nokogiri.org/ • JSON parser http://github.com/brianmario/yajl-ruby/ • CSV parser http://www.toastyapps.com/excelsior/ • HTTP client http://github.com/pauldix/typhoeus • Date http://github.com/rtomayko/date-performance
  • 48. About Caching • Ugly if you cache everywhere • More bugs and tough to debug includeing stale, data, inconsistent data, timing-based bugs. • Complicated: expire, security • Limit your user interface options
  • 49. Cache Store ActionController::Base.cache_store = :mem_cache_store, "localhost" ActionController::Base.cache_store = :compressed_mem_cache_store, "localhost" ActionController::Base.cache_store = :memory_store ActionController::Base.cache_store = :synchronized_memory_store ActionController::Base.cache_store = :file_store, "/path/to/cache/directory" ActionController::Base.cache_store = :drb_store, "druby://localhost:9192"
  • 50. View Caching • Page Caching • Action Caching • Fragment Caching
  • 51. Page Caching class ProductsController < ActionController caches_page :index def index; end end
  • 52. Action Caching class ProductsController < ActionController before_filter :authenticate, :only => [ :edit, :create ] caches_action :edit def index; end def create expire_page :action => :index expire_action :action => :edit end def edit; end end
  • 53. Fragment Caching <% cache(:key => ['all_available_products', @latest_product.created_at].join(':')) do %> All available products: <% end %> expire_fragment(:key => ['all_available_products', @latest_product.created_at].join(':'))
  • 54. Sweepers class StoreSweeper < ActionController::Caching::Sweeper # This sweeper is going to keep an eye on the Product model observe Product # If our sweeper detects that a Product was created call this def after_create(product) expire_cache_for(product) end # If our sweeper detects that a Product was updated call this def after_update(product) expire_cache_for(product) end # If our sweeper detects that a Product was deleted call this def after_destroy(product) expire_cache_for(product) end private def expire_cache_for(record) # Expire the list page now that we added a new product expire_page(:controller => '#{record}', :action => 'list') # Expire a fragment expire_fragment(:controller => '#{record}', :action => 'recent', :action_suffix => 'all_products') end end
  • 55. Caching yourself Rails.cache.read("city") # => nil Rails.cache.write("city", "Duckburgh") Rails.cache.read("city") # => "Duckburgh" Rails.cache.fetch("#{id}-data") do Book.sum(:amount, :conditions => { :category_id => self.category_ids } ) end
  • 56. Use Memcached • Free & open source, high-performance, distributed memory object caching system • an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.
  • 57. Memcached • Key: 256 characters • Data: 1mb • SET/ADD/REPLACE/GET operators • NOT persistent data store • caching “noreply” principle
  • 58. Caching secret • Key naming • Expiration
  • 59. Caching Expire • expire it after create/update/delete • race condition? lock it first. • reset it after update • race condition first time? lock it first. • set expire time • race condition? proactive cache refill
  • 61. SQL and ActiveRecord ORM is a high-level library that it’s easy to forget about efficiency until it becomes a problem.
  • 63. N+1 Queries # model class User < ActieRecord::Base has_one :car end class Car < ActiveRecord::Base belongs_to :user end # your controller def index @users = User.paginate( :page => params[:page], :per_page => 20 ) end # view <% @users.each do |user| %> <%= user.car.name %> <% end %>
  • 64. Add :include # your controller def index @users = User.paginate( :include => :car, :page => params [:page], :per_page => 20 ) end
  • 65. Bullet plugin • http://github.com/flyerhzm/bullet Help you reduce the number of queries with alerts (and growl).
  • 66. Missing indexing • Foreign key indexs • Columns that need to be sorted • Lookup fields • Columns that are used in a GROUP BY • http://github.com/eladmeidar/rails_indexes Rake tasks to find missing indexes.
  • 67. Only select you need Event.find(:all, :select => "id, title, description") class User < ActiveRecord::Base named_scope :short, :select => "id, name, email" end User.short.find(:all) • http://github.com/methodmissing/scrooge SQL query optimizer, so you query for only what your page needs.
  • 68. Replace :include to :join for some case Group.find(:all, :include => [ :group_memberships ], :conditions => [ "group_memberships.created_at > ?", Time.now - 30.days ] ) # you can replace :include to :join Group.find(:all, :joins => [ :group_memberships ], :conditions => [ "group_memberships.created_at > ?", Time.now - 30.days ] )
  • 69. Batch finding Article.find_each do |a| # iterate over all articles, in chunks of 1000 (the default) end Article.find_each(:conditions => { :published => true }, :batch_size => 100 ) do |a| # iterate over published articles in chunks of 100 end Article.find_in_batches do |articles| articles.each do |a| # articles is array of size 1000 end end Article.find_in_batches(batch_size => 100 ) do |articles| articles.each do |a| # iterate over all articles in chunks of 100 end end
  • 70. Transaction for group operations my_collection.each do |q| Quote.create({:phrase => q}) end # Add transaction Quote.transaction do my_collection.each do |q| Quote.create({:phrase => q}) end end
  • 71. SQL query planner • EXPLAIN keyword • http://github.com/dsboulder/query_reviewer
  • 73. Use Full-text search engine • Sphinx and thinking_sphinx plugin • Ferret gem and acts_as_ferret
  • 74. Use Constant for domain data class Rating < ActiveRecord::Base G = Rating.find_by_name('G') PG = Rating.find_by_name('PG') R = Rating.find_by_name('R') #.... end Rating::G Rating::PG Rating::R
  • 75. Counter cache class Topic < ActiveRecord::Base has_many :posts end class Posts < ActiveRecord::Base belongs_to :topic, :counter_cache => true end @topic.posts.size
  • 76. Store Your Reports • Aggregate reports via cron and rake
  • 77. AR Caching Plugins • http://github.com/nkallen/cache-money • http://github.com/fauna/interlock • http://github.com/defunkt/cache_fu • Need careful to go to these solution, because it’s very intrusive.
  • 78. Consider NoSQL data store • Key-value stores for high performance Redis, Tokyo Cabinet, Flare • Document stores for huge storage MongoDB, CouchDB • Record store for high scalability and availability Cassandra, HBase,Voldemort
  • 79. Use key-value store from now • Redis, Tokyo Cabinet are very very fast • Avoid touching the RDBMS when storing non-critical data, hit count, download count, online users count...etc
  • 80. Moneta • a unified interface to key/value stores • http://github.com/wycats/moneta/tree
  • 81. moneta supports: • File store for • S3 xattr • Basic File Store • Berkeley DB • Memcache store • Redis • In-memory store • SDBM • The xattrs in a file • Tokyo system • DataMapper • CouchDB
  • 82. moneta API: • #[](key) • #[]=(key, value) • #delete(key) • #key?(key) • #store(key, value, options) • #update_key(key, options): • #clear
  • 83. example begin # for developer has tokyo cabinet STORE = Moneta::Tyrant.new( :host => 'localhost', :port => 1978 ) rescue # for developer has not tokyo cabinet STORE = Moneta::BasicFile.new( :path => "tmp" ) end STORE["mykey"] = { :foo => 111 , :bar => 222 }
  • 84. Rails Metal a subset of Rack middleware • 2~3x faster than a controller, because it bypasses routes and controller. • APIs and anything which need not ActionView
  • 85. Use web server or CDN for static file • Web server is 10x faster than your application server • Set :x_sendfile to true if you use Apache mod_xsendfile or Lighttpd
  • 86. Web performance client-side analysis • http://developer.yahoo.com/yslow/ • http://code.google.com/speed/page-speed/
  • 87. Web performance Rules 14 • Make Fewer HTTP Requests • Make JavaScript and CSS External • Use a Content Delivery Network • Reduce DNS Lookups • Add an Expires Header • Minify JavaScript • Gzip Components • Avoid Redirects • Put Stylesheets at the Top • Remove Duplicates Scripts • Put Scripts at the Bottom • Configure ETags • Avoid CSS Expressions • Make Ajax Cacheable
  • 88.
  • 89. Use external programs def thumbnail(temp, target) system("/usr/local/bin/convert #{escape(temp)} -resize 48x48! #{escape(target}") end
  • 90. Write inline C/C++ code • RubyInline: Write foreign code within ruby code http://rubyinline.rubyforge.org/RubyInline/ • Rice: Ruby Interface for C++ Extensions http://rice.rubyforge.org/ • Ruby-FFI: a ruby extension for programmatically loading dynamic libraries http://github.com/ffi/ffi
  • 91. Reference • Advanced Rails Chap.6 Performance (O’Reilly) • Rails Rescue Handbook • Writing Efficient Ruby Code (Addison-Wesley) • Ruby on Rails Code Review (Peepcode) • Rails 2 Chap. 13 Security and Performance Enhancements (friendsof) • Deploying Rails Application Chap.9 Performance (Pragmatic) • http://guides.rubyonrails.org/caching_with_rails.html • http://guides.rubyonrails.org/performance_testing.html • http://railslab.newrelic.com/scaling-rails • http://antoniocangiano.com/2007/02/10/top-10-ruby-on-rails-performance-tips/ • http://www.engineyard.com/blog/2009/thats-not-a-memory-leak-its-bloat/ • http://jstorimer.com/ruby/2009/12/13/essential-rails-plugins-for-your-inner-dba.html • http://asciicasts.com/episodes/161-three-profiling-tools • http://robots.thoughtbot.com/post/163627511/a-grand-piano-for-your-violin
  • 92. So, how to scale? • Rails performance (AR...etc how to ruby code) • Web performance (yslow related) • Asynchrony Processing (Message queue) • HTTP Reverse Proxy Caching • Partition Component using SOA • Distributed Filesystem/Database
  • 93. TODO (maybe next time) • NoSQL: Key-value data store • Front-end web performance • HTTP reverse proxy caching