SlideShare a Scribd company logo
1 of 94
Download to read offline
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

SPA時代のOGPとの戦い方
SPA時代のOGPとの戦い方SPA時代のOGPとの戦い方
SPA時代のOGPとの戦い方Yoichi Toyota
 
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけRDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけRecruit Technologies
 
[데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기
[데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기 [데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기
[데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기 choi kyumin
 
Jenkins 2.0 Pipeline & Blue Ocean
Jenkins 2.0 Pipeline & Blue OceanJenkins 2.0 Pipeline & Blue Ocean
Jenkins 2.0 Pipeline & Blue OceanAkihiko Horiuchi
 
Little Big Data #1. 바닥부터 시작하는 데이터 인프라
Little Big Data #1. 바닥부터 시작하는 데이터 인프라Little Big Data #1. 바닥부터 시작하는 데이터 인프라
Little Big Data #1. 바닥부터 시작하는 데이터 인프라Seongyun Byeon
 
[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축
[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축
[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축Juhong Park
 
PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選Tomoya Kawanishi
 
Celery: The Distributed Task Queue
Celery: The Distributed Task QueueCelery: The Distributed Task Queue
Celery: The Distributed Task QueueRichard Leland
 
MariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システムMariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システムKouhei Sutou
 
Certificate 와 Provisioning Profile
Certificate 와 Provisioning ProfileCertificate 와 Provisioning Profile
Certificate 와 Provisioning Profilessuser9054541
 
PHP でも活用できる Makefile
PHP でも活用できる MakefilePHP でも活用できる Makefile
PHP でも活用できる MakefileShohei Okada
 
コンポーネント指向による、Reactのベストプラクティスとバッドプラクティス
コンポーネント指向による、Reactのベストプラクティスとバッドプラクティスコンポーネント指向による、Reactのベストプラクティスとバッドプラクティス
コンポーネント指向による、ReactのベストプラクティスとバッドプラクティスKohei Asai
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!kwatch
 
Luigi PyData presentation
Luigi PyData presentationLuigi PyData presentation
Luigi PyData presentationElias Freider
 
[2D1]Elasticsearch 성능 최적화
[2D1]Elasticsearch 성능 최적화[2D1]Elasticsearch 성능 최적화
[2D1]Elasticsearch 성능 최적화NAVER D2
 
Deview2020 유저가 좋은 작품(웹툰)을 만났을때
Deview2020 유저가 좋은 작품(웹툰)을 만났을때 Deview2020 유저가 좋은 작품(웹툰)을 만났을때
Deview2020 유저가 좋은 작품(웹툰)을 만났을때 choi kyumin
 
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint [D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint NAVER D2
 

What's hot (20)

Rails Best Practices
Rails Best PracticesRails Best Practices
Rails Best Practices
 
SPA時代のOGPとの戦い方
SPA時代のOGPとの戦い方SPA時代のOGPとの戦い方
SPA時代のOGPとの戦い方
 
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけRDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
 
[데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기
[데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기 [데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기
[데이터야놀자2107] 강남 출근길에 판교/정자역에 내릴 사람 예측하기
 
Jenkins 2.0 Pipeline & Blue Ocean
Jenkins 2.0 Pipeline & Blue OceanJenkins 2.0 Pipeline & Blue Ocean
Jenkins 2.0 Pipeline & Blue Ocean
 
Little Big Data #1. 바닥부터 시작하는 데이터 인프라
Little Big Data #1. 바닥부터 시작하는 데이터 인프라Little Big Data #1. 바닥부터 시작하는 데이터 인프라
Little Big Data #1. 바닥부터 시작하는 데이터 인프라
 
MySQL vs MonetDB Bencharmarks
MySQL vs MonetDB BencharmarksMySQL vs MonetDB Bencharmarks
MySQL vs MonetDB Bencharmarks
 
[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축
[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축
[NDC 2018] Spark, Flintrock, Airflow 로 구현하는 탄력적이고 유연한 데이터 분산처리 자동화 인프라 구축
 
PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選
 
Celery: The Distributed Task Queue
Celery: The Distributed Task QueueCelery: The Distributed Task Queue
Celery: The Distributed Task Queue
 
MariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システムMariaDBとMroongaで作る全言語対応超高速全文検索システム
MariaDBとMroongaで作る全言語対応超高速全文検索システム
 
Certificate 와 Provisioning Profile
Certificate 와 Provisioning ProfileCertificate 와 Provisioning Profile
Certificate 와 Provisioning Profile
 
PHP でも活用できる Makefile
PHP でも活用できる MakefilePHP でも活用できる Makefile
PHP でも活用できる Makefile
 
コンポーネント指向による、Reactのベストプラクティスとバッドプラクティス
コンポーネント指向による、Reactのベストプラクティスとバッドプラクティスコンポーネント指向による、Reactのベストプラクティスとバッドプラクティス
コンポーネント指向による、Reactのベストプラクティスとバッドプラクティス
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
Luigi PyData presentation
Luigi PyData presentationLuigi PyData presentation
Luigi PyData presentation
 
Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018
Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018
Apache Hadoop HDFSの最新機能の紹介(2018)#dbts2018
 
[2D1]Elasticsearch 성능 최적화
[2D1]Elasticsearch 성능 최적화[2D1]Elasticsearch 성능 최적화
[2D1]Elasticsearch 성능 최적화
 
Deview2020 유저가 좋은 작품(웹툰)을 만났을때
Deview2020 유저가 좋은 작품(웹툰)을 만났을때 Deview2020 유저가 좋은 작품(웹툰)을 만났을때
Deview2020 유저가 좋은 작품(웹툰)을 만났을때
 
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint [D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
 

Viewers also liked

ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2RORLAB
 
ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1RORLAB
 
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 RailsNataly 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 friendForrest 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/RailsPaul 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 RailsAgnieszka Figiel
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and RailsWen-Tien Chang
 
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 IntroductionThomas Fuchs
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017John 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

Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009pratiknaik
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performanceEngine 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 beginnerUmair 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 RubyHiroshi 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 PerforcePerforce
 
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_
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.jsorkaplan
 
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 2015Masahiro Nagano
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHiroshi SHIBATA
 
Ricardo Sanchez - Ruby projects of interest for devops
Ricardo Sanchez - Ruby projects of interest for devopsRicardo Sanchez - Ruby projects of interest for devops
Ricardo Sanchez - Ruby projects of interest for devopsSVDevOps
 

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
 
Ricardo Sanchez - Ruby projects of interest for devops
Ricardo Sanchez - Ruby projects of interest for devopsRicardo Sanchez - Ruby projects of interest for devops
Ricardo Sanchez - 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 LearningWen-Tien Chang
 
淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2淺談 Startup 公司的軟體開發流程 v2
淺談 Startup 公司的軟體開發流程 v2Wen-Tien Chang
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails TutorialWen-Tien Chang
 
ALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateALPHAhackathon: How to collaborate
ALPHAhackathon: How to collaborateWen-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.0Wen-Tien Chang
 
RubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingRubyConf Taiwan 2012 Opening & Closing
RubyConf Taiwan 2012 Opening & ClosingWen-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

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 

Recently uploaded (20)

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

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