From 190eb9b07f3f48d07137b25c11dca99b40fd72b1 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 10 Jan 2009 02:56:14 +0000 Subject: Some examples for perf testing --- railties/doc/guides/html/performance_testing.html | 164 +++++++++++++++++---- railties/doc/guides/source/performance_testing.txt | 99 ++++++++++++- 2 files changed, 231 insertions(+), 32 deletions(-) (limited to 'railties/doc/guides') diff --git a/railties/doc/guides/html/performance_testing.html b/railties/doc/guides/html/performance_testing.html index 4a4d15eac6..dbbd52fa2b 100644 --- a/railties/doc/guides/html/performance_testing.html +++ b/railties/doc/guides/html/performance_testing.html @@ -2,7 +2,7 @@ - Performance testing Rails Applications + Performance Testing Rails Applications @@ -204,6 +204,8 @@ ul#navMain {
  • Generating performance tests
  • +
  • Examples
  • +
  • Modes
  • Metrics
  • @@ -233,7 +235,7 @@ ul#navMain { Other Profiling Tools
  • - Commercial products dedicated to Rails Perfomance + Commercial products
  • Changelog @@ -242,7 +244,7 @@ ul#navMain {
    -

    Performance testing Rails Applications

    +

    Performance Testing Rails Applications

    This guide covers the various ways of performance testing a Ruby on Rails application. By referring to this guide, you will be able to:

    @@ -319,9 +321,96 @@ http://www.gnu.org/software/src-highlite --> end end

    Which you can modify to suit your needs.

    -

    1.2. Modes

    +

    1.2. Examples

    +

    Let’s assume your application have the following controller and model:

    +
    +
    +
    # routes.rb
    +map.root :controller => 'home'
    +map.resources :posts
    +
    +# home_controller.rb
    +class HomeController < ApplicationController
    +  def dashboard
    +    @users = User.last_ten(:include => :avatars)
    +    @posts = Post.all_today
    +  end
    +end
    +
    +# posts_controller.rb
    +class PostsController < ApplicationController
    +  def create
    +    @post = Post.create(params[:post])
    +    redirect_to(@post)
    +  end
    +end
    +
    +# post.rb
    +class Post < ActiveRecord::Base
    +  before_save :recalculate_costly_stats
    +
    +  def slow_method
    +    # I fire gallzilion queries sleeping all around
    +  end
    +
    +  private
    +
    +  def recalculate_costly_stats
    +    # CPU heavy calculations
    +  end
    +end
    +

    1.2.1. Controller Example

    +

    Performance tests are special kind of integration tests. This allows you to use get and post methods inside the performance tests.

    +

    Performance tests for the controller code above can be something like:

    +
    +
    +
    require 'test_helper'
    +require 'performance_test_help'
    +
    +class PostPerformanceTest < ActionController::PerformanceTest
    +  def setup
    +    # Application requires logged in user
    +    login_as(:lifo)
    +  end
    +
    +  def test_homepage
    +    get '/dashboard'
    +  end
    +
    +  def test_creating_new_post
    +    post '/posts', :post => { :body => 'lifo is fooling you' }
    +  end
    +end
    +

    You can find more details about get and post methods in API documentation of integration testing.

    +

    1.2.2. Model Example

    +

    Even though performance tests are integration tests and hence closer to request/response cycle by nature, it doesn’t prevent us from testing pure model code inside. Performance test for Post model above can be somewhat like:

    +
    +
    +
    require 'test_helper'
    +require 'performance_test_help'
    +
    +class PostModelTest < ActionController::PerformanceTest
    +  def test_creation
    +    Post.create :body => 'still fooling you', :cost => '100'
    +  end
    +
    +  def test_slow_method
    +    # Using posts(:awesome) fixture
    +    posts(:awesome).slow_method
    +  end
    +end
    +

    1.3. Modes

    Performance test cases can be run in two modes : Benchmarking and Profling.

    -

    1.2.1. Benchmarking

    +

    1.3.1. Benchmarking

    Benchmarking helps you find out how fast are your test cases. Each Test case is run 4 times in this mode. To run performance tests in benchmarking mode:

    $ rake test:benchmark
    -

    1.2.2. Profiling

    +

    1.3.2. Profiling

    Profiling helps introspect into your test cases and figure out which are the slow parts. Each Test case is run 1 time in this mode. To run performance tests in profiling mode:

    $ rake test:profile
    -

    1.3. Metrics

    +

    1.4. Metrics

    Benchmarking and profiling run performance test cases in various modes to help precisely figure out the where the problem lies.

    -

    1.3.1. Wall Time

    +

    1.4.1. Wall Time

    Measures the real world time elapsed during the test run. It is affected by any other processes concurrently running on the system.

    Mode : Benchmarking

    -

    1.3.2. Process Time

    +

    1.4.2. Process Time

    Measures the time taken by the process. It is unaffected by any other processes running concurrently on the same system. Hence, process time is likely to be constant for any given performance test, irrespective of the machine load.

    Mode : Profiling

    -

    1.3.3. Memory

    +

    1.4.3. Memory

    Measures the amount of memory used for the performance test case.

    Mode : Benchmarking, Profiling [Requires GC Patched Ruby]

    -

    1.3.4. Objects

    +

    1.4.4. Objects

    Measures the number of objects allocated for the performance test case.

    Mode : Benchmarking, Profiling [Requires GC Patched Ruby]

    -

    1.3.5. GC Runs

    +

    1.4.5. GC Runs

    Measures the number of times GC was invoked for the performance test case.

    Mode : Benchmarking [Requires GC Patched Ruby]

    -

    1.3.6. GC Time

    +

    1.4.6. GC Time

    Measures the amount of time spent in GC for the performance test case.

    Mode : Benchmarking [Requires GC Patched Ruby]

    -

    1.4. Understanding the output

    +

    1.5. Understanding the output

    Performance tests generate different outputs inside tmp/performance directory based on the mode it is run in and the metric.

    -

    1.4.1. Benchmarking

    +

    1.5.1. Benchmarking

    In benchmarking mode, performance tests generate two types of outputs :

    Command line

    This is the primary form of output in benchmarking mode. Example :

    @@ -421,7 +510,7 @@ http://www.gnu.org/software/src-highlite --> 0.00740450000000004,2009-01-09T03:54:47Z,,2.3.0.master.859e150,ruby-1.8.6.110,i686-darwin9.0.0 0.00603150000000008,2009-01-09T03:54:57Z,,2.3.0.master.859e150,ruby-1.8.6.111,i686-darwin9.1.0 0.00771250000000012,2009-01-09T15:46:03Z,,2.3.0.master.859e150,ruby-1.8.6.110,i686-darwin9.0.0
    -

    1.4.2. Profiling

    +

    1.5.2. Profiling

    Command line

    This is the very basic form of output in profiling mode. Example :

    @@ -439,10 +528,11 @@ http://www.gnu.org/software/src-highlite -->

    Graph output shows how long each method takes to run, which methods call it and which methods it calls. Check ruby prof documentation for a better explaination.

    Tree

    Tree output is profiling information in calltree format for use by kcachegrind and similar tools.

    -

    1.5. Installing GC Patched Ruby

    +

    1.6. Installing GC Patched Ruby

    To get the best from Rails performance test cases, you need to build a special Ruby binary with some super powers - GC patch for measuring GC Runs/Time and memory/object allocation profiling. This process is very straight forward. If you’ve never compiled a Ruby binary before, you can follow the following steps to build a ruby binary inside your home directory:

    -

    1.5.1. Compile

    +

    1.6.1. Instllation

    Compile Ruby and apply this GC Patch:

    +

    1.6.2. Download and Extract

    [lifo@null ~]$ mkdir rubygc
     [lifo@null ~]$ wget <download the latest stable ruby from ftp://ftp.ruby-lang.org/pub/ruby>
     [lifo@null ~]$ tar -xzvf <ruby-version.tar.gz>
    -[lifo@null ~]$ cd <ruby-version>
    -[lifo@null ruby-version]$ curl http://rubyforge.org/tracker/download.php/1814/7062/17676/3291/ruby186gc.patch | patch -p0
    -[lifo@null ruby-version]$ ./configure --prefix=/Users/lifo/rubygc
    +[lifo@null ~]$ cd <ruby-version>
    +

    1.6.3. Apply the patch

    +
    +
    +
    [lifo@null ruby-version]$ curl http://rubyforge.org/tracker/download.php/1814/7062/17676/3291/ruby186gc.patch | patch -p0
    +

    1.6.4. Configure and Install

    +

    The following will install ruby in your home directory’s /rubygc directory. Make sure to replace <homedir> with a full patch to your actual home directory.

    +
    +
    +
    [lifo@null ruby-version]$ ./configure --prefix=/<homedir>/rubygc
     [lifo@null ruby-version]$ make && make install
    -

    1.5.2. Prepare aliases

    -

    Add the following lines in your ~/.profile for convenience:

    +

    1.6.5. Prepare aliases

    +

    For convenience, add the following lines in your ~/.profile after replacing <username> with your :

    -
    alias gcruby='/Users/lifo/rubygc/bin/ruby'
    -alias gcrake='/Users/lifo/rubygc/bin/rake'
    -alias gcgem='/Users/lifo/rubygc/bin/gem'
    -alias gcirb='/Users/lifo/rubygc/bin/irb'
    -alias gcrails='/Users/lifo/rubygc/bin/rails'
    +
    alias gcruby='~/rubygc/bin/ruby'
    +alias gcrake='~/rubygc/bin/rake'
    +alias gcgem='~/rubygc/bin/gem'
    +alias gcirb='~/rubygc/bin/irb'
    +alias gcrails='~/rubygc/bin/rails'
    -

    1.5.3. Install rubygems and some basic gems

    +

    1.6.6. Install rubygems and some basic gems

    Download Rubygems and install it from source. Rubygem’s README file should have necessary installation instructions.

    Additionally, installa the following gems :

      @@ -591,8 +694,9 @@ http://www.gnu.org/software/src-highlite -->
    -

    5. Commercial products dedicated to Rails Perfomance

    +

    5. Commercial products

    +

    Rails has been lucky to have three startups dedicated to Rails specific performance tools:

    • diff --git a/railties/doc/guides/source/performance_testing.txt b/railties/doc/guides/source/performance_testing.txt index f42b3686b7..e58927b758 100644 --- a/railties/doc/guides/source/performance_testing.txt +++ b/railties/doc/guides/source/performance_testing.txt @@ -1,4 +1,4 @@ -Performance testing Rails Applications +Performance Testing Rails Applications ====================================== This guide covers the various ways of performance testing a Ruby on Rails application. By referring to this guide, you will be able to: @@ -58,6 +58,98 @@ end Which you can modify to suit your needs. +=== Examples === + +Let's assume your application have the following controller and model: + +[source, ruby] +---------------------------------------------------------------------------- +# routes.rb +map.root :controller => 'home' +map.resources :posts + +# home_controller.rb +class HomeController < ApplicationController + def dashboard + @users = User.last_ten(:include => :avatars) + @posts = Post.all_today + end +end + +# posts_controller.rb +class PostsController < ApplicationController + def create + @post = Post.create(params[:post]) + redirect_to(@post) + end +end + +# post.rb +class Post < ActiveRecord::Base + before_save :recalculate_costly_stats + + def slow_method + # I fire gallzilion queries sleeping all around + end + + private + + def recalculate_costly_stats + # CPU heavy calculations + end +end +---------------------------------------------------------------------------- + +==== Controller Example ==== + +Performance tests are special kind of integration tests. This allows you to use +get+ and +post+ methods inside the performance tests. + +Performance tests for the controller code above can be something like: + +[source, ruby] +---------------------------------------------------------------------------- +require 'test_helper' +require 'performance_test_help' + +class PostPerformanceTest < ActionController::PerformanceTest + def setup + # Application requires logged in user + login_as(:lifo) + end + + def test_homepage + get '/dashboard' + end + + def test_creating_new_post + post '/posts', :post => { :body => 'lifo is fooling you' } + end +end +---------------------------------------------------------------------------- + +You can find more details about +get+ and +post+ methods in API documentation of integration testing. + +==== Model Example ==== + +Even though performance tests are integration tests and hence closer to request/response cycle by nature, it doesn't prevent us from testing pure model code inside. Performance test for +Post+ model above can be somewhat like: + +[source, ruby] +---------------------------------------------------------------------------- +require 'test_helper' +require 'performance_test_help' + +class PostModelTest < ActionController::PerformanceTest + def test_creation + Post.create :body => 'still fooling you', :cost => '100' + end + + def test_slow_method + # Using posts(:awesome) fixture + posts(:awesome).slow_method + end +end +---------------------------------------------------------------------------- + === Modes === Performance test cases can be run in two modes : Benchmarking and Profling. @@ -344,7 +436,10 @@ Michael Koziarski has an http://www.therailsway.com/2009/1/6/requests-per-second * http://rails-analyzer.rubyforge.org/[Rails Analyzer] * http://www.flyingmachinestudios.com/projects/[Palmist] -== Commercial products dedicated to Rails Perfomance == +== Commercial products == + +Rails has been lucky to have three startups dedicated to Rails specific performance tools: + * http://www.newrelic.com[New Relic] * http://www.fiveruns.com[Fiveruns] * http://scoutapp.com[Scout] -- cgit v1.2.3