SlideShare uma empresa Scribd logo
1 de 50
Baixar para ler offline
0/49




Rails Application Optimization
Techniques & Tools

Stefan Kaes
www.railsexpress.de
skaes@gmx.net

                                 Back
                                 Close
1/49




A tiny piece of history



                          Back
                          Close
Performance Tuning                                              2/49

• Trying to improve performance without measuring is foolish.
• If your app’s design has an inherent performance problem,
  you will need a costly redesign.
• Planning ahead for an established performance goal will
  help you cut down on the cost of performance improvement
  work.
• There’s no need to optimize every page of your web app.
• Focus on your app’s hot spots (frequently visited pages),
  and measure continuously during development.




                                                                Back
                                                                Close
Performance Parameters                                        3/49



Latency
   How fast can you answer a request?
Throughput
   How many requests can you process per second?
Utilization
   Are your servers/components idle most of the time?
Cost Efficiency
  Performance per unit cost


Compute mean, min, max, standard deviation (if applicable)
Standard deviation will tell you how reliable your data is.
                                                              Back
                                                              Close
Benchmarking Tools                                                 4/49
• Rails log files (debug level ≥ Logger::DEBUG)
• Rails Analyzer Tools(requires logging to syslog)
• Rails benchmarker script (script/benchmarker)
• Tools provided by DB vendor
• Apache Bench (ab or ab2)
• httperf
• railsbench
   – downloadable from http://rubyforge.org/projects/railsbench/




                                                                   Back
                                                                   Close
railsbench                                             5/49

measures raw performance of Rails request processing
configured through

 • benchmark definitions
   $RAILS ROOT/config/benchmarks.yml
 • benchmark class configuration
   $RAILS ROOT/config/benchmarks.rb

stores benchmark data in

   $RAILS PERF DATA

indexed by date and benchmark name
uses additional Rails environment benchmarking

                                                       Back
                                                       Close
railsbench usage                                                  6/49

  perf run 100 quot;-bm=welcome optionsquot; [data file]

run 100 iterations of benchmark with given options, print data

  perf diff 100 quot;-bm=all optsquot; quot;opts1quot; quot;opts2quot; [file1] [file2]

run 100 iterations of benchmark, print data comparing opts1 and
opts2

  perf times data file 1 ...

print performance data contained in files

  perf comp [-narrow] data file 1 data file 2

print comparison of raw data files
                                                                  Back
                                                                  Close
railsbench options                                                     7/49
-log[= level]
   turn on logging (defaults to no logging). optionally override log
   level.
-nocache
   turn off Rails caching
-path
   exit after printing $:
-svlPV
   run test using Ruby Performance Validator
-patched gc
   use patched GC




                                                                       Back
                                                                       Close
Ruby Profiling Tools                                                    8/49
 • Ruby Profiler
 • Zen Profiler
 • rubyprof
 • Rails profiler script
 • Ruby Performance Validator (commercial, Windows only)

All but the last are pretty much useless for Rails performance work.
railsbench has builtin support for RPVL:

  run_urls 100 -svlPV -bm=welcome ...

will start RPVL and run the named benchmark with given options


                                                                       Back
                                                                       Close
Top Rails Performance Problems                                9/49

Depends on who you ask, but these are my favorites:

 • slow helper methods
 • complicated routes
 • associations
 • retrieving too much from DB
 • slow session storage

Judging from my experience, DB performance is usually not a
bottleneck.
Instantiating ActiveRecord objects is more expensive.



                                                              Back
                                                              Close
Available Session Containers                                                             10/49
In Memory
    Fastest, but you will lose all sessions on app server crash/restart. Restricted to
    1 app server process. Doesn’t scale.
File System
     Easy setup. One file (below /tmp) for each session. Scales by using NFS or
     NAS (beware 10K active sessions!). Slower than
Database/ActiveRecordStore
    Easy setup (comes with Rails distribution). Much slower than
Database/SQLSessionStore
    Uses ARStore session table format. But does all processing using raw SQL
    queries. Needs tweaking if you want additional fields on session entries. setup
memcached
   Slightly faster than SQLSessionStore. Presumably scales best. Very tunable.
   Automatic session cleaning. Harder to obtain statistics. setup
DrbStore
   Can be used on platforms where memcached is not available. Slower than
   memcached. No automatic expiry (but could be added quickly).

                                                                                         Back
                                                                                         Close
Cachable Elements                                                       11/49
Pages
   Fastest. Complete pages are stored on file system. Web server
   bypasses app server for rendering. Scales through NFS or NAS.
   Problematic if your app requires login.
Actions
   Second fastest option. Caches the result of invoking actions on
   controllers. User login id can be used as part of the storage key.
Fragments
   Very useful for caching small fragments (hence the name) of
   HTML produced during request processing. Can be made user
   aware.

Action caching is just a special case of fragment caching.
Several storage containers are available for fragment caching.

                                                                        Back
                                                                        Close
Storage Options for Fragment Caching                                 12/49
In Memory
   Blazing speed! If your app is running fast enough with 1 app
   server process, go for it!
File System
    Reasonably fast. Expiring fragments using regular expressions
    for keys is slow.
DrbStore
   Comparable to FileStore. Expiring fragments is faster.
memcached
  Faster and more scalable than DrbStore. Doesn’t support
  expiring by regular expression.

The size of the actual code in Rails to handle caching is small.
It would be easy to extend so that all of the above options can be
used concurrently.                                                   Back
                                                                     Close
ActionController Issues                                              13/49

Components

I suggest to avoid components. I haven’t found any good use for
them, yet.
Each embedded component will be handled using a fresh request
cycle.
Can always be replaced by helper methods and partials.

Filters

If you are using components, make sure you don’t rerun your filters
n times. Better pass along context information explicitely.
You can use the skip_filter method for this. It will be evaluated
at class load time, so no runtime overhead during request
processing.                                                          Back
                                                                     Close
ActionView Issues                                                         14/49

Instance variables

For each request, one controller instance and one view instance will
be instantiated.
Instance variables created during controller processing will be
transfered to the view instance (using instance_variable_get
and instance_variable_set)
So: avoid creating instance variables in controller actions, which will
not be used in the view (not always possible, see filters).




                                                                          Back
                                                                          Close
Slow Helper Methods                                                       15/49

    Consider:
      pluralize (n, ’ post’ )
1



    This will create a new Inflector instance, and try to derive the correct
    plural for ’post’. This is expensive. Just do
      pluralize (n, ’ post’ , ’ posts’ )
1




                                                                              Back
                                                                              Close
link to and url for                                                                16/49

    Due to the route generation involved, url for and link to are
    among the slowest helper methods around.

     <%= link to ”look here for something interesting” ,
1
            { :controller => ”recipe”, :action => edit, :id => @recipe.id },
2
            { :class => ” edit link ” } %>
3




      • both hash arguments undergo heavy massage in the Rails bowel: symbolizing,
        html escaping, sorting, validation
      • the routing module determines the shortest possible route to the controller,
        action and id

    A much more efficient way to write this is:

    <a href=quot;/recipe/edit/<%=#{recipe.id}%>quot; class=quot;edit_linkquot;>
    look here for something interesting
    </a>
                                                                                       Back
                                                                                       Close
ActiveRecord Issues                                                            17/49
    Accessing AR objects via association proxies is (comparetively) slow.
    You can prefetch associated objects using :include
      class Article
1
       belongs to :author
2
      end
3
      Article . find ( :all , :include => :author)
4



    Use piggy backing for has_one or belongs_to relations.
      class Article
1
        piggy back :author name, :from => :author, :attributes => [:name]
2
      end
3
      article = Article . find ( :all , :piggy => :author)
4
      puts article .author name
5



    Field values are retrieved from the DB as strings (mostly).
    Type conversion happens on each access.
    =⇒ cache converted values, if you use them several times during one request.
                                                                                   Back
                                                                                   Close
Caching Column Formatting                                             18/49

Computationally expensive transformations on AR fields can be
cached (in the DB, using memcached, a DRb process)
Example: textilize

   • I’ve analyzed an application, where 30% CPU was spent on
      textilizing. Another 30% were spent on GC. And about 10% on
      URL recognition.
   • Caching the formatted fields in the DB eliminated the textilize
      overhead completely.




                                                                      Back
At one point in time a plugin existed for this task.

                                                                      Close
Ruby’s Interpreter is Slow                                  19/49
 • no byte code, no JIT, interprets ASTs directly
 • doesn’t perform any code optimization at compile time:
         method inlining
     –
         strength reduction
     –
         constant propagation
     –
         common subexpression elimination
     –
         loop invariant detection
     –
         loop unrolling
     –

=⇒
Performance aware Ruby programming can increase
performance significantly!


                                                            Back
                                                            Close
Complexity of Ruby Language Elements                                  20/49
Local Variable access: O(1)
   index into array, computed at parse time
                              expected O(1)
Instance Variable Access:
    hash access by literal
                expected O(1)
Method Call:
      • hash access to determine literal value (quot;fquot; ⇒ :f)
      • method search along inheritance chain
      • hash accesses to get the method
      • there’s also a method cache (which helps a bit)
      • construction of argument array on heap (unless attr reader)


Recommendation:

 • don’t add method abstractions needlessly
 • use attr accessors as external interfaces only
 • use local variables to short circuit repeated hash accesses
                                                                      Back
                                                                      Close
Avoiding Repeated Hash Access                                                     21/49

     def submit to remote(name, value, options = {})
1
       options[ :with ] ||= ’ Form.serialize( this .form)’
2
       options[:html ] ||= {}
3
       options[:html ][ :type ] = ’ button’
4
       options[:html ][ :onclick ] = ”#{remote function(options)}; return false ; ”
5
       options[:html ][ :name] = name
6
       options[:html ][ :value ] = value
7
       tag(” input” , options[:html ], false )
8
     end
9



    This code is both simpler and faster:
     def submit to remote(name, value, options = {})
1
       options[ :with ] ||= ’ Form.serialize( this .form)’
2
       html = (options[:html ] ||= {})
3
       html[:type ] = ’ button’
4
       html[ :onclick ] = ”#{remote function(options)}; return false ; ”
5
       html[:name] = name
6
       html[:value ] = value
7
       tag(” input” , html, false )
8
     end
9
                                                                                      Back
                                                                                      Close
Caching Data in Instance Variables                                     22/49

    If you need the same data structure repeatedly during request
    processing, consider caching on controller (or view) instance level.

    Turn
      def capital letters
1
        ( ”A” .. ”Z” ). to a
2
      end
3



    into
      def capital letters
1
        @capital letters ||= ( ”A” .. ”Z” ). to a
2
      end
3




                                                                           Back
                                                                           Close
Caching Data in Class Variables                                       23/49

    If your data has a reasonable size to keep around permanently and
    is used on a hot application path, consider caching on class level.

    Turn
      def capital letters
1
        ( ”A” .. ”Z” ). to a
2
      end
3



    into
      @@capital letters = (”A” .. ”Z” ). to a
1
2
      def capital letters
3
        @@capital letters
4
      end
5



    the cached value could be a query from the database, e.g. guest
    user account.
                                                                          Back
                                                                          Close
Coding Variable Caching Efficiently                                          24/49

    Turn
      def actions
1
        unless @actions
2
          # do something complicated and costly to determine action’s value
3
          @actions = expr
4
        end
5
        @actions
6
      end
7



    into
      def actions
1
        @actions ||=
2
          begin
3
            # do something complicated and costly to determine action’s value
4
            expr
5
          end
6
      end
7




                                                                                Back
                                                                                Close
Defining Constants vs. Inlining                                                           25/49

    Less than optimal:
     def validate find options (options)
1
       options. assert valid keys ( :conditions , :include , :joins , :limit , :offset ,
2
                                    :order , :select , :readonly, :group, :from          )
3
     end
4



    Better:
     VALID FIND OPTIONS = [
1
       :conditions , :include , :joins , :limit ,
2
        :offset , :order , :select , :readonly, :group, :from ]
3
4
     def validate find options (options)
5
       options. assert valid keys (VALID FIND OPTIONS)
6
     end
7



    Faster and much easier to customize.


                                                                                             Back
                                                                                             Close
Local Variables are Cheap                                                               26/49

    Consider:
          sql << ” GROUP BY #{options[:group]} ” if options[:group]
1



    vs.
          if opts = options[:group]
1
            sql << ” GROUP BY #{opts} ”
2
          end
3



    or
          opts = options[:group] and sql << ” GROUP BY #{opts} ”
1



    Alas,
          sql << ” GROUP BY #{opts} ” if opts = options[:group]
1



    won’t work, because matz refused to implement it (at least last time I asked for it).

                                                                                            Back
                                                                                            Close
Beware Variable Capture When Defining                                            27/49
     Methods
     Defining a new method passing a block, captures the defining environment.
     This can cause memory leaks.
      def define attr method(name, value=nil, &block)
 1
        sing = class << self; self ; end
 2
        sing.send :alias method, ” original #{name}”, name
 3
        if block given?
 4
          sing.send :define method, name, &block
 5
        else
 6
          # use eval instead of a block to work around a memory leak in dev
 7
          # mode in fcgi
 8
          sing. class eval ”def #{name}; #{value.to s.inspect}; end”
 9
        end
10
      end
11



     It’s usually preferable to use eval instead of define_method, unless you need
     the variable capture.

                                                                                     Back
                                                                                     Close
Be Careful w.r.t. Logging                                                         28/49
      • set the production log level to something other than DEBUG.
      • don’t log to log level INFO what should be logged to DEBUG.

    This is a bad idiom:
     logger.debug ”args: #{hash.keys.sort.join ( ’ ’ )}” if logger
1



    hash.keys.sort.join(’ ’) will be evaluated and the arg string will be
    constructed, even if logger.level == ERROR.

    Instead do this:
     logger.debug ”args: #{hash.keys.sort.join ( ’ ’ )}” if logger && logger.debug?
1




                                                                                      Back
                                                                                      Close
ObjectSpace.each object                                    29/49

    Contrary to popular belief
     ObjectSpace.each object(Class) {|c| f(c) }
1



    is just as slow as
     ObjectSpace.each object {|o| o.is a?(Class) && f(o) }
1



    In both cases, every object on the heap is inspected!
    Don’t call it in production mode on a per request basis.




    BTW: ObjectSpace.each object has dubious semantics         Back
                                                               Close
Ruby’s Memory Management                                           30/49
 • designed for batch scripts, not long running server apps
 • tries to minimize memory usage
 • simple mark and sweep algorithm
 • uses malloc to manage contiguous blocks of Ruby objects (Ruby
   heap)
 • complex data structures:
    – only references to C structs are stored on Ruby heap
    – comprises strings, arrays, hashes, local variable maps,
      scopes, etc.
 • eases writing C extensions
Current C interface makes it hard to implement generational GC
=⇒ unlikely to get generational GC in the near future
Maybe Ruby2 will have it (but Ruby2 is a bit like Perl6)           Back
                                                                   Close
Why Ruby GC is suboptimal for Rails                              31/49

ASTs are stored on the Ruby heap and will be processed on each
collection
  usually the biggest part of non garbage for Rails apps

Sweep phase depends on size of heap, not size of non garbage
  can’t increase the heap size above certain limits

More heap gets added, if
  size of freelist after collection < FREE_MIN
a constant defined in gc.c as 4096

200.000 heap slots are a good lower bound for live data
  for typical Rails heaps, 4096 is way too small!                Back
                                                                 Close
Improving GC Performance                                             32/49

    Control GC from the Rails dispatcher:
     # excerpt from dispatch. fcgi
1

     RailsFCGIHandler.process! nil, 50
2



    Will disable Ruby GC and call GC.start after 50 requests have been
    processed

    However, small requests and large requests are treated equally

     • heap could grow too large
     • performance for small pages suffers
     • Ruby will still deallocate heap blocks if empty after GC


                                                                         Back
                                                                         Close
Patching Ruby’s Garbage Collector                                                     33/49

Download latest railsbench package. Patch Ruby using file
rubygc.patch, recompile and reinstall binaries and docs.
Tune GC using environment variables
RUBY HEAP MIN SLOTS
   initial heap size in number of slots used (default 10000)
RUBY HEAP FREE MIN
   number of free heap slots that should be available after GC (default 4096)
RUBY GC MALLOC LIMIT
   amount of C data structures (in bytes) which can be allocated without triggering
   GC (default 8000000)

Recommended values to start with:
     RUBY_HEAP_MIN_SLOTS =    600000
     RUBY_GC_MALLOC_LIMIT = 60000000
     RUBY_HEAP_FREE_MIN   =   100000

Running the previous benchmark again, gives much nicer GC stats                       Back
                                                                                      Close
Compile Time Template Optimization                                    34/49

Many helper calls in Erb templates can be evaluated at template
compile time.
<%= end_form_tag %>    ===>   </form>

It’s a complete waste to do it over and over again on a per request
basis
For some calls, we know what the output should be like, even if we
don’t have all arguments available
<%= link_to quot;Editquot;,
     {:controller => quot;recipequot;, :action => edit, :id => @record},
     {:class => quot;edit_linkquot;} %>

could be replaced by
<a href=quot;/recipe/edit/<%= @record.to_param %>quot;
   class=quot;edit_linkquot;>Edit</a>
                                                                      Back
                                                                      Close
Rails Template Optimizer
                                                                      35/49
Uses Ryan Davis’ ParseTree package and ruby2ruby class
Retrieves AST of ActionView render method after initial compilation
Transforms AST using

 • helper method inlining
 • dead code removal
 • unused variable removal (from partials)
 • hash merging
 • constant evaluation
 • strength reduction
 • constant call evaluation
 • symbolic evaluation
until AST cannot be simplified further
Compiles new AST into optimized render method using eval              Back
                                                                      Close
Optimizer Customization
TemplateOptimizer::INLINE_CALLS.merge( ... )                           36/49

TemplateOptimizer::EVALUATE_CALLS.merge( ... )

TemplateOptimizer::EVALUATE_CONSTANTS.merge( ... )

TemplateOptimizer::IGNORED_METHODS.merge( ... )

TemplateOptimizer::CALLS_RETURNING_STRINGS.merge( ... )




Optimizer Restrictions

url hashes cannot be optimized if the hash domain isn’t constant
if your app hosts several domains, url hashes cannot be optimized if
:only_path => false gets passed


                                                                       Back
                                                                       Close
Optimizer Performance Benchmark

Run this morning (1000 -bm=uncached -mysql session . . . ):            37/49


page    c1 real     c2 real c1 r/s c2 r/s c1 ms/r c2 ms/r      c1/c2
 1:    22.52100     6.80167   44.4 147.0    22.52    6.80       3.31
 2:    39.61467     6.86433   25.2 145.7    39.61    6.86       5.77
 3:    40.67167     6.43267   24.6 155.5    40.67    6.43       6.32
 4:    33.89600     5.80767   29.5 172.2    33.90    5.81       5.84

all: 136.70333 25.90633       29.3   154.4   34.18     6.48    5.28

GC:     c1 real     c2 real c1 #gc c2 #gc    c1 gc%   c2 gc%   c1/c2
       11.06067     2.91533   50.0   20.0      8.09    11.25    2.50

What do you say?
;-)



Project Status: α
Licensing: undecided                                                   Back
                                                                       Close
End                                                                   38/49

Thanks very much for your attention.
If you appreciated this session, you might consider buying my book,
available early next year from Addison Wesley, as part of the
”Professional Ruby” series.
Questions?




                                                                      Back
                                                                      Close
ActiveRecordStore vs.                                                                39/49
SQLSessionStore
page c1 real c2 real c1 r/s c2 r/s c1 ms/r c2 ms/r c1/c2
 1:  2.80733 1.14600 356.2 872.6      2.81    1.15 2.45
 2:  3.91667 1.33867 255.3 747.0      3.92    1.34 2.93
 3:  5.21367 1.94300 191.8 514.7      5.21    1.94 2.68
 4:  5.65633 2.41167 176.8 414.7      5.66    2.41 2.35
 5: 11.64600 7.39600   85.9 135.2    11.65    7.40 1.57
 6: 16.83333 15.10933  59.4   66.2   16.83   15.11 1.11
 7: 17.09333 15.52067  58.5   64.4   17.09   15.52 1.10
 8:  8.19267 6.78133 122.1 147.5      8.19    6.78 1.21

GC:     c1 real     c2 real c1 #gc c2 #gc           c1 gc%      c2 gc% c1/c2
        3.83667     2.76133   25.0   20.0             5.38        5.35 1.25

Additional details regarding SQLSessionStore and memcached can be found here:
http://railsexpress.de/blog/articles/2005/12/19/roll-your-own-sql-session-store

http://railsexpress.de/blog/articles/2006/01/24/using-memcached-for-ruby-on-rails-
session-storage
                                                                                     Back
                                                                                     Close
Configuring Rails to use                                          40/49
    SQLSessionStore with Mysql/Postgres
    Download latest version from my web site
    Put Ruby source under lib directory.
    Adjust environment.rb:
     require ’ sql session store ’
1
     ActionController::CgiRequest::DEFAULT SESSION OPTIONS.update(
2
       :database manager => SQLSessionStore)
3
4
     require ’ mysql session’
5
     SQLSessionStore.session class = MysqlSession
6



    For Postgres, use
      require ’ postgresql session’
1
      SQLSessionStore.session class = PostgresqlSession
2



    Note: requires Postgres 8.1!                                     Back
                                                                     Close
memcached Session Storage Setup                                     41/49

     Download memcache-client: http://rubyforge.org/frs/?group id=1266
      require ’ memcache’
 1
      require ’ memcache util’
 2
 3
      # memcache defaults, environments may override these settings
 4
      unless defined? MEMCACHE OPTIONS then
 5
        MEMCACHE OPTIONS = {
 6
           :debug => false,
 7
           :namespace => ’my name space’,
 8
           :readonly => false
 9
        }
10
      end
11
12
      # memcache configuration
13
      unless defined? MEMCACHE CONFIG then
14
        File .open ”#{RAILS ROOT}/config/memcache.yml” do |memcache|
15
           MEMCACHE CONFIG = YAML ::load memcache
16
         end
17
      end
18


                                                                         Back
                                                                         Close
# Connect to memcache
 1
       unless defined? CACHE then
 2
                                                                                         42/49
         CACHE = MemCache.new MEMCACHE OPTIONS
 3
         CACHE.servers = MEMCACHE CONFIG[RAILS ENV]
 4
       end
 5
 6
       # Configure the session manager to use memcache data store.
7
       ActionController::CgiRequest::DEFAULT SESSION OPTIONS.update(
 8
              :database manager => CGI::Session::MemCacheStore,
 9
              :cache => CACHE, :expires => 3600 ∗ 12)
10



     YAML file:
       production:
1
         − localhost:11211
2
3
       development:
4
         − localhost:11211
5
6
       benchmarking:
7
         − localhost:11211
8



     Don’t forget to start the server:   memcached&         Session Container Overview

                                                                                         Back
                                                                                         Close
GC Statistics (unpatched GC)
                                                                 43/49

GC data file: c:/home/skaes/perfdata/xp/perf_runworld.gc.txt

collections            :         66
garbage total          :    1532476
gc time total (sec)    :          1.86
garbage per request    :       2554.13
requests per collection:          9.09

                     mean   stddev%            min         max
gc time(ms):        28.08      22.0          15.00       32.00
heap slots :    223696.00       0.0      223696.00   223696.00
live       :    200429.88       0.4      199298.00   201994.00
freed      :     23266.12       3.3       21702.00    24398.00
freelist   :         0.00       0.0           0.00        0.00




                                                                 Back
                                                                 Close
GC Statistics (patched GC)
                                                                 44/49

GC data file: c:/home/skaes/perfdata/xp/perf_runworld.gc.txt

collections            :          5
garbage total          :    1639636
gc time total (sec)    :          0.64
garbage per request    :       2732.73
requests per collection:        120.00

                     mean   stddev%            min         max
gc time(ms):       148.75       6.0         141.00      157.00
heap slots :    600000.00       0.0      600000.00   600000.00
live       :    201288.00       0.2      200773.00   201669.00
freed      :    398712.00       0.1      398331.00   399227.00
freelist   :         0.00       0.0           0.00        0.00




                                                                 Back
                                                                 Close
ObjectSpace.each object riddle                 45/49

     Can you explain the output of this script?
     def f (o)
 1

       1000.times { Array.new }; 1
 2

     end
 3

 4

     puts ObjectSpace.each object { }
 5

 6

     f (0)
 7

 8

     puts ObjectSpace.each object { }
 9

10

     100.times do
11

       puts ObjectSpace.each object { |o| f (o) }
12

     end
13



                                                    Back
                                                    Close
config/benchmarks.rb                                                 46/49

     # create benchmarker instance
 1
 2
     RAILS BENCHMARKER = RailsBenchmarkWithActiveRecordStore.new
 3
 4
     # RAILS BENCHMARKER.relative url root = ’/’
 5
 6
     # if your session manager isn’t ActiveRecordStore, or if you don’t
 7
     # want sesssions to be cleaned after benchmarking, just use
 8
     # RAILS BENCHMARKER = RailsBenchmark.new
 9
10
     # create session data required to run the benchmark
11
     # customize this code if your benchmark needs session data
12
13
     require ’ user’
14
     RAILS BENCHMARKER.session data = {:user id => 23}
15
16




                                                                          Back
                                                                          Close
config/benchmarks.yml                       47/49
default:
    uri: /

all: default, empty, welcome, cat, letter

empty:
    uri: /empty/index
    new_session: true

welcome:
    uri: /welcome/index
    new_session: true

letter:
    uri: /rezept/letter/G

cat:
       uri: /rezept/cat/Hauptspeise
       query_params: page=5


                                            Back
                                            Close
Coding link to manually                                                              48/49
page     c1 real      c2 real c1 r/s        c2 r/s c1 ms/r c2 ms/r           c1/c2
 1:      1.38033      1.36467 724.5          732.8    1.38    1.36            1.01
 2:      2.21867      2.32833 450.7          429.5    2.22    2.33            0.95
 3:      2.90067      2.92733 344.7          341.6    2.90    2.93            0.99
 4:      2.87467      2.77600 347.9          360.2    2.87    2.78            1.04
 5:     11.10467      7.63033   90.1         131.1   11.10    7.63            1.46
 6:     12.47900      6.38567   80.1         156.6   12.48    6.39            1.95
 7:     12.31767      6.46900   81.2         154.6   12.32    6.47            1.90
 8:     11.72433      6.27067   85.3         159.5   11.72    6.27            1.87

GC:      c1 real      c2 real c1 #gc        c2 #gc     c1 gc%     c2 gc%     c1/c2
         6.48867      3.16600   43.0          23.0      11.38       8.76      1.87

 • the relation c1/c2 depends on the hardware used. This seems to indicate that
      the quality of the Ruby implementation / OS memory management has a
      significant influence on relative performance.
 • you probably shouldn’t manually code every link_to. just use this method on
      pages with a large number of links. (Or wait for my template optimzer :-)


                                                                                     Back
                                                                                     Close
Measuring GC Performance Using                       49/49
railsbench
  perf_run_gc n quot;-bm=benchmark . . .quot; [data f ile]

runs named benchmark, producing a raw data file

  perf_times_gc data f ile

prints a summary for data in raw data file




                                                     Back
                                                     Close

Mais conteúdo relacionado

Mais procurados

How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHiroshi SHIBATA
 
Gate of Agile Web Development
Gate of Agile Web DevelopmentGate of Agile Web Development
Gate of Agile Web DevelopmentKoichi ITO
 
Find bottleneck and tuning in Java Application
Find bottleneck and tuning in Java ApplicationFind bottleneck and tuning in Java Application
Find bottleneck and tuning in Java Applicationguest1f2740
 
30 Minutes To CPAN
30 Minutes To CPAN30 Minutes To CPAN
30 Minutes To CPANdaoswald
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mrubyHiroshi SHIBATA
 
20140419 oedo rubykaigi04
20140419 oedo rubykaigi0420140419 oedo rubykaigi04
20140419 oedo rubykaigi04Hiroshi SHIBATA
 
20140425 ruby conftaiwan2014
20140425 ruby conftaiwan201420140425 ruby conftaiwan2014
20140425 ruby conftaiwan2014Hiroshi SHIBATA
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHiroshi SHIBATA
 
Distributed Applications with Perl & Gearman
Distributed Applications with Perl & GearmanDistributed Applications with Perl & Gearman
Distributed Applications with Perl & GearmanIssac Goldstand
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mrubyHiroshi SHIBATA
 
Performance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-MechanizePerformance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-Mechanizecoreygoldberg
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpAll Things Open
 
J Ruby Whirlwind Tour
J Ruby Whirlwind TourJ Ruby Whirlwind Tour
J Ruby Whirlwind Touroscon2007
 
Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012Dan Kuebrich
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
 

Mais procurados (20)

How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
 
Gate of Agile Web Development
Gate of Agile Web DevelopmentGate of Agile Web Development
Gate of Agile Web Development
 
Find bottleneck and tuning in Java Application
Find bottleneck and tuning in Java ApplicationFind bottleneck and tuning in Java Application
Find bottleneck and tuning in Java Application
 
30 Minutes To CPAN
30 Minutes To CPAN30 Minutes To CPAN
30 Minutes To CPAN
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
 
20140925 rails pacific
20140925 rails pacific20140925 rails pacific
20140925 rails pacific
 
Practical ngx_mruby
Practical ngx_mrubyPractical ngx_mruby
Practical ngx_mruby
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mruby
 
CPAN Training
CPAN TrainingCPAN Training
CPAN Training
 
20140419 oedo rubykaigi04
20140419 oedo rubykaigi0420140419 oedo rubykaigi04
20140419 oedo rubykaigi04
 
20140425 ruby conftaiwan2014
20140425 ruby conftaiwan201420140425 ruby conftaiwan2014
20140425 ruby conftaiwan2014
 
Usenix lisa 2011
Usenix lisa 2011Usenix lisa 2011
Usenix lisa 2011
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rb
 
Distributed Applications with Perl & Gearman
Distributed Applications with Perl & GearmanDistributed Applications with Perl & Gearman
Distributed Applications with Perl & Gearman
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mruby
 
Performance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-MechanizePerformance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-Mechanize
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and Gulp
 
J Ruby Whirlwind Tour
J Ruby Whirlwind TourJ Ruby Whirlwind Tour
J Ruby Whirlwind Tour
 
Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 

Semelhante a Rails Application Optimization Techniques & Tools

Cast Iron Cloud Integration Best Practices
Cast Iron Cloud Integration Best PracticesCast Iron Cloud Integration Best Practices
Cast Iron Cloud Integration Best PracticesSarath Ambadas
 
Flink Forward SF 2017: Malo Deniélou - No shard left behind: Dynamic work re...
Flink Forward SF 2017: Malo Deniélou -  No shard left behind: Dynamic work re...Flink Forward SF 2017: Malo Deniélou -  No shard left behind: Dynamic work re...
Flink Forward SF 2017: Malo Deniélou - No shard left behind: Dynamic work re...Flink Forward
 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDinakar Guniguntala
 
OTM Performance Review and Benchmarking
OTM Performance Review and BenchmarkingOTM Performance Review and Benchmarking
OTM Performance Review and BenchmarkingMavenWire
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011bobmcwhirter
 
Beat the devil: towards a Drupal performance benchmark
Beat the devil: towards a Drupal performance benchmarkBeat the devil: towards a Drupal performance benchmark
Beat the devil: towards a Drupal performance benchmarkPedro González Serrano
 
Ansible & Salt - Vincent Boon
Ansible & Salt - Vincent BoonAnsible & Salt - Vincent Boon
Ansible & Salt - Vincent BoonMyNOG
 
Copper: A high performance workflow engine
Copper: A high performance workflow engineCopper: A high performance workflow engine
Copper: A high performance workflow enginedmoebius
 
Evolution of MongoDB Replicaset and Its Best Practices
Evolution of MongoDB Replicaset and Its Best PracticesEvolution of MongoDB Replicaset and Its Best Practices
Evolution of MongoDB Replicaset and Its Best PracticesMydbops
 
Evolution Of MongoDB Replicaset
Evolution Of MongoDB ReplicasetEvolution Of MongoDB Replicaset
Evolution Of MongoDB ReplicasetM Malai
 
OpenLDAP Replication Strategies
OpenLDAP Replication StrategiesOpenLDAP Replication Strategies
OpenLDAP Replication StrategiesGavin Henry
 
Oracle R12 EBS Performance Tuning
Oracle R12 EBS Performance TuningOracle R12 EBS Performance Tuning
Oracle R12 EBS Performance TuningScott Jenner
 
Reducing Risk When Upgrading MySQL
Reducing Risk When Upgrading MySQLReducing Risk When Upgrading MySQL
Reducing Risk When Upgrading MySQLKenny Gryp
 
Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010
Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010
Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010Arun Gupta
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteDr Nic Williams
 
Drupal Performance : DrupalCamp North
Drupal Performance : DrupalCamp NorthDrupal Performance : DrupalCamp North
Drupal Performance : DrupalCamp NorthPhilip Norton
 
Drupal Efficiency
Drupal EfficiencyDrupal Efficiency
Drupal Efficiencysmattoon
 

Semelhante a Rails Application Optimization Techniques & Tools (20)

Cast Iron Cloud Integration Best Practices
Cast Iron Cloud Integration Best PracticesCast Iron Cloud Integration Best Practices
Cast Iron Cloud Integration Best Practices
 
Flink Forward SF 2017: Malo Deniélou - No shard left behind: Dynamic work re...
Flink Forward SF 2017: Malo Deniélou -  No shard left behind: Dynamic work re...Flink Forward SF 2017: Malo Deniélou -  No shard left behind: Dynamic work re...
Flink Forward SF 2017: Malo Deniélou - No shard left behind: Dynamic work re...
 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on Kubernetes
 
OTM Performance Review and Benchmarking
OTM Performance Review and BenchmarkingOTM Performance Review and Benchmarking
OTM Performance Review and Benchmarking
 
Sql optimize
Sql optimizeSql optimize
Sql optimize
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
 
Beat the devil: towards a Drupal performance benchmark
Beat the devil: towards a Drupal performance benchmarkBeat the devil: towards a Drupal performance benchmark
Beat the devil: towards a Drupal performance benchmark
 
Ansible & Salt - Vincent Boon
Ansible & Salt - Vincent BoonAnsible & Salt - Vincent Boon
Ansible & Salt - Vincent Boon
 
Copper: A high performance workflow engine
Copper: A high performance workflow engineCopper: A high performance workflow engine
Copper: A high performance workflow engine
 
MySQL Replication
MySQL ReplicationMySQL Replication
MySQL Replication
 
Evolution of MongoDB Replicaset and Its Best Practices
Evolution of MongoDB Replicaset and Its Best PracticesEvolution of MongoDB Replicaset and Its Best Practices
Evolution of MongoDB Replicaset and Its Best Practices
 
Evolution Of MongoDB Replicaset
Evolution Of MongoDB ReplicasetEvolution Of MongoDB Replicaset
Evolution Of MongoDB Replicaset
 
OpenLDAP Replication Strategies
OpenLDAP Replication StrategiesOpenLDAP Replication Strategies
OpenLDAP Replication Strategies
 
Oracle R12 EBS Performance Tuning
Oracle R12 EBS Performance TuningOracle R12 EBS Performance Tuning
Oracle R12 EBS Performance Tuning
 
Reducing Risk When Upgrading MySQL
Reducing Risk When Upgrading MySQLReducing Risk When Upgrading MySQL
Reducing Risk When Upgrading MySQL
 
Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010
Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010
Getting Started with Rails on GlassFish (Hands-on Lab) - Spark IT 2010
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
 
Drupal Performance : DrupalCamp North
Drupal Performance : DrupalCamp NorthDrupal Performance : DrupalCamp North
Drupal Performance : DrupalCamp North
 
Drupal Efficiency
Drupal EfficiencyDrupal Efficiency
Drupal Efficiency
 
XPages Performance
XPages PerformanceXPages Performance
XPages Performance
 

Último

What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

Rails Application Optimization Techniques & Tools

  • 1. 0/49 Rails Application Optimization Techniques & Tools Stefan Kaes www.railsexpress.de skaes@gmx.net Back Close
  • 2. 1/49 A tiny piece of history Back Close
  • 3. Performance Tuning 2/49 • Trying to improve performance without measuring is foolish. • If your app’s design has an inherent performance problem, you will need a costly redesign. • Planning ahead for an established performance goal will help you cut down on the cost of performance improvement work. • There’s no need to optimize every page of your web app. • Focus on your app’s hot spots (frequently visited pages), and measure continuously during development. Back Close
  • 4. Performance Parameters 3/49 Latency How fast can you answer a request? Throughput How many requests can you process per second? Utilization Are your servers/components idle most of the time? Cost Efficiency Performance per unit cost Compute mean, min, max, standard deviation (if applicable) Standard deviation will tell you how reliable your data is. Back Close
  • 5. Benchmarking Tools 4/49 • Rails log files (debug level ≥ Logger::DEBUG) • Rails Analyzer Tools(requires logging to syslog) • Rails benchmarker script (script/benchmarker) • Tools provided by DB vendor • Apache Bench (ab or ab2) • httperf • railsbench – downloadable from http://rubyforge.org/projects/railsbench/ Back Close
  • 6. railsbench 5/49 measures raw performance of Rails request processing configured through • benchmark definitions $RAILS ROOT/config/benchmarks.yml • benchmark class configuration $RAILS ROOT/config/benchmarks.rb stores benchmark data in $RAILS PERF DATA indexed by date and benchmark name uses additional Rails environment benchmarking Back Close
  • 7. railsbench usage 6/49 perf run 100 quot;-bm=welcome optionsquot; [data file] run 100 iterations of benchmark with given options, print data perf diff 100 quot;-bm=all optsquot; quot;opts1quot; quot;opts2quot; [file1] [file2] run 100 iterations of benchmark, print data comparing opts1 and opts2 perf times data file 1 ... print performance data contained in files perf comp [-narrow] data file 1 data file 2 print comparison of raw data files Back Close
  • 8. railsbench options 7/49 -log[= level] turn on logging (defaults to no logging). optionally override log level. -nocache turn off Rails caching -path exit after printing $: -svlPV run test using Ruby Performance Validator -patched gc use patched GC Back Close
  • 9. Ruby Profiling Tools 8/49 • Ruby Profiler • Zen Profiler • rubyprof • Rails profiler script • Ruby Performance Validator (commercial, Windows only) All but the last are pretty much useless for Rails performance work. railsbench has builtin support for RPVL: run_urls 100 -svlPV -bm=welcome ... will start RPVL and run the named benchmark with given options Back Close
  • 10. Top Rails Performance Problems 9/49 Depends on who you ask, but these are my favorites: • slow helper methods • complicated routes • associations • retrieving too much from DB • slow session storage Judging from my experience, DB performance is usually not a bottleneck. Instantiating ActiveRecord objects is more expensive. Back Close
  • 11. Available Session Containers 10/49 In Memory Fastest, but you will lose all sessions on app server crash/restart. Restricted to 1 app server process. Doesn’t scale. File System Easy setup. One file (below /tmp) for each session. Scales by using NFS or NAS (beware 10K active sessions!). Slower than Database/ActiveRecordStore Easy setup (comes with Rails distribution). Much slower than Database/SQLSessionStore Uses ARStore session table format. But does all processing using raw SQL queries. Needs tweaking if you want additional fields on session entries. setup memcached Slightly faster than SQLSessionStore. Presumably scales best. Very tunable. Automatic session cleaning. Harder to obtain statistics. setup DrbStore Can be used on platforms where memcached is not available. Slower than memcached. No automatic expiry (but could be added quickly). Back Close
  • 12. Cachable Elements 11/49 Pages Fastest. Complete pages are stored on file system. Web server bypasses app server for rendering. Scales through NFS or NAS. Problematic if your app requires login. Actions Second fastest option. Caches the result of invoking actions on controllers. User login id can be used as part of the storage key. Fragments Very useful for caching small fragments (hence the name) of HTML produced during request processing. Can be made user aware. Action caching is just a special case of fragment caching. Several storage containers are available for fragment caching. Back Close
  • 13. Storage Options for Fragment Caching 12/49 In Memory Blazing speed! If your app is running fast enough with 1 app server process, go for it! File System Reasonably fast. Expiring fragments using regular expressions for keys is slow. DrbStore Comparable to FileStore. Expiring fragments is faster. memcached Faster and more scalable than DrbStore. Doesn’t support expiring by regular expression. The size of the actual code in Rails to handle caching is small. It would be easy to extend so that all of the above options can be used concurrently. Back Close
  • 14. ActionController Issues 13/49 Components I suggest to avoid components. I haven’t found any good use for them, yet. Each embedded component will be handled using a fresh request cycle. Can always be replaced by helper methods and partials. Filters If you are using components, make sure you don’t rerun your filters n times. Better pass along context information explicitely. You can use the skip_filter method for this. It will be evaluated at class load time, so no runtime overhead during request processing. Back Close
  • 15. ActionView Issues 14/49 Instance variables For each request, one controller instance and one view instance will be instantiated. Instance variables created during controller processing will be transfered to the view instance (using instance_variable_get and instance_variable_set) So: avoid creating instance variables in controller actions, which will not be used in the view (not always possible, see filters). Back Close
  • 16. Slow Helper Methods 15/49 Consider: pluralize (n, ’ post’ ) 1 This will create a new Inflector instance, and try to derive the correct plural for ’post’. This is expensive. Just do pluralize (n, ’ post’ , ’ posts’ ) 1 Back Close
  • 17. link to and url for 16/49 Due to the route generation involved, url for and link to are among the slowest helper methods around. <%= link to ”look here for something interesting” , 1 { :controller => ”recipe”, :action => edit, :id => @recipe.id }, 2 { :class => ” edit link ” } %> 3 • both hash arguments undergo heavy massage in the Rails bowel: symbolizing, html escaping, sorting, validation • the routing module determines the shortest possible route to the controller, action and id A much more efficient way to write this is: <a href=quot;/recipe/edit/<%=#{recipe.id}%>quot; class=quot;edit_linkquot;> look here for something interesting </a> Back Close
  • 18. ActiveRecord Issues 17/49 Accessing AR objects via association proxies is (comparetively) slow. You can prefetch associated objects using :include class Article 1 belongs to :author 2 end 3 Article . find ( :all , :include => :author) 4 Use piggy backing for has_one or belongs_to relations. class Article 1 piggy back :author name, :from => :author, :attributes => [:name] 2 end 3 article = Article . find ( :all , :piggy => :author) 4 puts article .author name 5 Field values are retrieved from the DB as strings (mostly). Type conversion happens on each access. =⇒ cache converted values, if you use them several times during one request. Back Close
  • 19. Caching Column Formatting 18/49 Computationally expensive transformations on AR fields can be cached (in the DB, using memcached, a DRb process) Example: textilize • I’ve analyzed an application, where 30% CPU was spent on textilizing. Another 30% were spent on GC. And about 10% on URL recognition. • Caching the formatted fields in the DB eliminated the textilize overhead completely. Back At one point in time a plugin existed for this task. Close
  • 20. Ruby’s Interpreter is Slow 19/49 • no byte code, no JIT, interprets ASTs directly • doesn’t perform any code optimization at compile time: method inlining – strength reduction – constant propagation – common subexpression elimination – loop invariant detection – loop unrolling – =⇒ Performance aware Ruby programming can increase performance significantly! Back Close
  • 21. Complexity of Ruby Language Elements 20/49 Local Variable access: O(1) index into array, computed at parse time expected O(1) Instance Variable Access: hash access by literal expected O(1) Method Call: • hash access to determine literal value (quot;fquot; ⇒ :f) • method search along inheritance chain • hash accesses to get the method • there’s also a method cache (which helps a bit) • construction of argument array on heap (unless attr reader) Recommendation: • don’t add method abstractions needlessly • use attr accessors as external interfaces only • use local variables to short circuit repeated hash accesses Back Close
  • 22. Avoiding Repeated Hash Access 21/49 def submit to remote(name, value, options = {}) 1 options[ :with ] ||= ’ Form.serialize( this .form)’ 2 options[:html ] ||= {} 3 options[:html ][ :type ] = ’ button’ 4 options[:html ][ :onclick ] = ”#{remote function(options)}; return false ; ” 5 options[:html ][ :name] = name 6 options[:html ][ :value ] = value 7 tag(” input” , options[:html ], false ) 8 end 9 This code is both simpler and faster: def submit to remote(name, value, options = {}) 1 options[ :with ] ||= ’ Form.serialize( this .form)’ 2 html = (options[:html ] ||= {}) 3 html[:type ] = ’ button’ 4 html[ :onclick ] = ”#{remote function(options)}; return false ; ” 5 html[:name] = name 6 html[:value ] = value 7 tag(” input” , html, false ) 8 end 9 Back Close
  • 23. Caching Data in Instance Variables 22/49 If you need the same data structure repeatedly during request processing, consider caching on controller (or view) instance level. Turn def capital letters 1 ( ”A” .. ”Z” ). to a 2 end 3 into def capital letters 1 @capital letters ||= ( ”A” .. ”Z” ). to a 2 end 3 Back Close
  • 24. Caching Data in Class Variables 23/49 If your data has a reasonable size to keep around permanently and is used on a hot application path, consider caching on class level. Turn def capital letters 1 ( ”A” .. ”Z” ). to a 2 end 3 into @@capital letters = (”A” .. ”Z” ). to a 1 2 def capital letters 3 @@capital letters 4 end 5 the cached value could be a query from the database, e.g. guest user account. Back Close
  • 25. Coding Variable Caching Efficiently 24/49 Turn def actions 1 unless @actions 2 # do something complicated and costly to determine action’s value 3 @actions = expr 4 end 5 @actions 6 end 7 into def actions 1 @actions ||= 2 begin 3 # do something complicated and costly to determine action’s value 4 expr 5 end 6 end 7 Back Close
  • 26. Defining Constants vs. Inlining 25/49 Less than optimal: def validate find options (options) 1 options. assert valid keys ( :conditions , :include , :joins , :limit , :offset , 2 :order , :select , :readonly, :group, :from ) 3 end 4 Better: VALID FIND OPTIONS = [ 1 :conditions , :include , :joins , :limit , 2 :offset , :order , :select , :readonly, :group, :from ] 3 4 def validate find options (options) 5 options. assert valid keys (VALID FIND OPTIONS) 6 end 7 Faster and much easier to customize. Back Close
  • 27. Local Variables are Cheap 26/49 Consider: sql << ” GROUP BY #{options[:group]} ” if options[:group] 1 vs. if opts = options[:group] 1 sql << ” GROUP BY #{opts} ” 2 end 3 or opts = options[:group] and sql << ” GROUP BY #{opts} ” 1 Alas, sql << ” GROUP BY #{opts} ” if opts = options[:group] 1 won’t work, because matz refused to implement it (at least last time I asked for it). Back Close
  • 28. Beware Variable Capture When Defining 27/49 Methods Defining a new method passing a block, captures the defining environment. This can cause memory leaks. def define attr method(name, value=nil, &block) 1 sing = class << self; self ; end 2 sing.send :alias method, ” original #{name}”, name 3 if block given? 4 sing.send :define method, name, &block 5 else 6 # use eval instead of a block to work around a memory leak in dev 7 # mode in fcgi 8 sing. class eval ”def #{name}; #{value.to s.inspect}; end” 9 end 10 end 11 It’s usually preferable to use eval instead of define_method, unless you need the variable capture. Back Close
  • 29. Be Careful w.r.t. Logging 28/49 • set the production log level to something other than DEBUG. • don’t log to log level INFO what should be logged to DEBUG. This is a bad idiom: logger.debug ”args: #{hash.keys.sort.join ( ’ ’ )}” if logger 1 hash.keys.sort.join(’ ’) will be evaluated and the arg string will be constructed, even if logger.level == ERROR. Instead do this: logger.debug ”args: #{hash.keys.sort.join ( ’ ’ )}” if logger && logger.debug? 1 Back Close
  • 30. ObjectSpace.each object 29/49 Contrary to popular belief ObjectSpace.each object(Class) {|c| f(c) } 1 is just as slow as ObjectSpace.each object {|o| o.is a?(Class) && f(o) } 1 In both cases, every object on the heap is inspected! Don’t call it in production mode on a per request basis. BTW: ObjectSpace.each object has dubious semantics Back Close
  • 31. Ruby’s Memory Management 30/49 • designed for batch scripts, not long running server apps • tries to minimize memory usage • simple mark and sweep algorithm • uses malloc to manage contiguous blocks of Ruby objects (Ruby heap) • complex data structures: – only references to C structs are stored on Ruby heap – comprises strings, arrays, hashes, local variable maps, scopes, etc. • eases writing C extensions Current C interface makes it hard to implement generational GC =⇒ unlikely to get generational GC in the near future Maybe Ruby2 will have it (but Ruby2 is a bit like Perl6) Back Close
  • 32. Why Ruby GC is suboptimal for Rails 31/49 ASTs are stored on the Ruby heap and will be processed on each collection usually the biggest part of non garbage for Rails apps Sweep phase depends on size of heap, not size of non garbage can’t increase the heap size above certain limits More heap gets added, if size of freelist after collection < FREE_MIN a constant defined in gc.c as 4096 200.000 heap slots are a good lower bound for live data for typical Rails heaps, 4096 is way too small! Back Close
  • 33. Improving GC Performance 32/49 Control GC from the Rails dispatcher: # excerpt from dispatch. fcgi 1 RailsFCGIHandler.process! nil, 50 2 Will disable Ruby GC and call GC.start after 50 requests have been processed However, small requests and large requests are treated equally • heap could grow too large • performance for small pages suffers • Ruby will still deallocate heap blocks if empty after GC Back Close
  • 34. Patching Ruby’s Garbage Collector 33/49 Download latest railsbench package. Patch Ruby using file rubygc.patch, recompile and reinstall binaries and docs. Tune GC using environment variables RUBY HEAP MIN SLOTS initial heap size in number of slots used (default 10000) RUBY HEAP FREE MIN number of free heap slots that should be available after GC (default 4096) RUBY GC MALLOC LIMIT amount of C data structures (in bytes) which can be allocated without triggering GC (default 8000000) Recommended values to start with: RUBY_HEAP_MIN_SLOTS = 600000 RUBY_GC_MALLOC_LIMIT = 60000000 RUBY_HEAP_FREE_MIN = 100000 Running the previous benchmark again, gives much nicer GC stats Back Close
  • 35. Compile Time Template Optimization 34/49 Many helper calls in Erb templates can be evaluated at template compile time. <%= end_form_tag %> ===> </form> It’s a complete waste to do it over and over again on a per request basis For some calls, we know what the output should be like, even if we don’t have all arguments available <%= link_to quot;Editquot;, {:controller => quot;recipequot;, :action => edit, :id => @record}, {:class => quot;edit_linkquot;} %> could be replaced by <a href=quot;/recipe/edit/<%= @record.to_param %>quot; class=quot;edit_linkquot;>Edit</a> Back Close
  • 36. Rails Template Optimizer 35/49 Uses Ryan Davis’ ParseTree package and ruby2ruby class Retrieves AST of ActionView render method after initial compilation Transforms AST using • helper method inlining • dead code removal • unused variable removal (from partials) • hash merging • constant evaluation • strength reduction • constant call evaluation • symbolic evaluation until AST cannot be simplified further Compiles new AST into optimized render method using eval Back Close
  • 37. Optimizer Customization TemplateOptimizer::INLINE_CALLS.merge( ... ) 36/49 TemplateOptimizer::EVALUATE_CALLS.merge( ... ) TemplateOptimizer::EVALUATE_CONSTANTS.merge( ... ) TemplateOptimizer::IGNORED_METHODS.merge( ... ) TemplateOptimizer::CALLS_RETURNING_STRINGS.merge( ... ) Optimizer Restrictions url hashes cannot be optimized if the hash domain isn’t constant if your app hosts several domains, url hashes cannot be optimized if :only_path => false gets passed Back Close
  • 38. Optimizer Performance Benchmark Run this morning (1000 -bm=uncached -mysql session . . . ): 37/49 page c1 real c2 real c1 r/s c2 r/s c1 ms/r c2 ms/r c1/c2 1: 22.52100 6.80167 44.4 147.0 22.52 6.80 3.31 2: 39.61467 6.86433 25.2 145.7 39.61 6.86 5.77 3: 40.67167 6.43267 24.6 155.5 40.67 6.43 6.32 4: 33.89600 5.80767 29.5 172.2 33.90 5.81 5.84 all: 136.70333 25.90633 29.3 154.4 34.18 6.48 5.28 GC: c1 real c2 real c1 #gc c2 #gc c1 gc% c2 gc% c1/c2 11.06067 2.91533 50.0 20.0 8.09 11.25 2.50 What do you say? ;-) Project Status: α Licensing: undecided Back Close
  • 39. End 38/49 Thanks very much for your attention. If you appreciated this session, you might consider buying my book, available early next year from Addison Wesley, as part of the ”Professional Ruby” series. Questions? Back Close
  • 40. ActiveRecordStore vs. 39/49 SQLSessionStore page c1 real c2 real c1 r/s c2 r/s c1 ms/r c2 ms/r c1/c2 1: 2.80733 1.14600 356.2 872.6 2.81 1.15 2.45 2: 3.91667 1.33867 255.3 747.0 3.92 1.34 2.93 3: 5.21367 1.94300 191.8 514.7 5.21 1.94 2.68 4: 5.65633 2.41167 176.8 414.7 5.66 2.41 2.35 5: 11.64600 7.39600 85.9 135.2 11.65 7.40 1.57 6: 16.83333 15.10933 59.4 66.2 16.83 15.11 1.11 7: 17.09333 15.52067 58.5 64.4 17.09 15.52 1.10 8: 8.19267 6.78133 122.1 147.5 8.19 6.78 1.21 GC: c1 real c2 real c1 #gc c2 #gc c1 gc% c2 gc% c1/c2 3.83667 2.76133 25.0 20.0 5.38 5.35 1.25 Additional details regarding SQLSessionStore and memcached can be found here: http://railsexpress.de/blog/articles/2005/12/19/roll-your-own-sql-session-store http://railsexpress.de/blog/articles/2006/01/24/using-memcached-for-ruby-on-rails- session-storage Back Close
  • 41. Configuring Rails to use 40/49 SQLSessionStore with Mysql/Postgres Download latest version from my web site Put Ruby source under lib directory. Adjust environment.rb: require ’ sql session store ’ 1 ActionController::CgiRequest::DEFAULT SESSION OPTIONS.update( 2 :database manager => SQLSessionStore) 3 4 require ’ mysql session’ 5 SQLSessionStore.session class = MysqlSession 6 For Postgres, use require ’ postgresql session’ 1 SQLSessionStore.session class = PostgresqlSession 2 Note: requires Postgres 8.1! Back Close
  • 42. memcached Session Storage Setup 41/49 Download memcache-client: http://rubyforge.org/frs/?group id=1266 require ’ memcache’ 1 require ’ memcache util’ 2 3 # memcache defaults, environments may override these settings 4 unless defined? MEMCACHE OPTIONS then 5 MEMCACHE OPTIONS = { 6 :debug => false, 7 :namespace => ’my name space’, 8 :readonly => false 9 } 10 end 11 12 # memcache configuration 13 unless defined? MEMCACHE CONFIG then 14 File .open ”#{RAILS ROOT}/config/memcache.yml” do |memcache| 15 MEMCACHE CONFIG = YAML ::load memcache 16 end 17 end 18 Back Close
  • 43. # Connect to memcache 1 unless defined? CACHE then 2 42/49 CACHE = MemCache.new MEMCACHE OPTIONS 3 CACHE.servers = MEMCACHE CONFIG[RAILS ENV] 4 end 5 6 # Configure the session manager to use memcache data store. 7 ActionController::CgiRequest::DEFAULT SESSION OPTIONS.update( 8 :database manager => CGI::Session::MemCacheStore, 9 :cache => CACHE, :expires => 3600 ∗ 12) 10 YAML file: production: 1 − localhost:11211 2 3 development: 4 − localhost:11211 5 6 benchmarking: 7 − localhost:11211 8 Don’t forget to start the server: memcached& Session Container Overview Back Close
  • 44. GC Statistics (unpatched GC) 43/49 GC data file: c:/home/skaes/perfdata/xp/perf_runworld.gc.txt collections : 66 garbage total : 1532476 gc time total (sec) : 1.86 garbage per request : 2554.13 requests per collection: 9.09 mean stddev% min max gc time(ms): 28.08 22.0 15.00 32.00 heap slots : 223696.00 0.0 223696.00 223696.00 live : 200429.88 0.4 199298.00 201994.00 freed : 23266.12 3.3 21702.00 24398.00 freelist : 0.00 0.0 0.00 0.00 Back Close
  • 45. GC Statistics (patched GC) 44/49 GC data file: c:/home/skaes/perfdata/xp/perf_runworld.gc.txt collections : 5 garbage total : 1639636 gc time total (sec) : 0.64 garbage per request : 2732.73 requests per collection: 120.00 mean stddev% min max gc time(ms): 148.75 6.0 141.00 157.00 heap slots : 600000.00 0.0 600000.00 600000.00 live : 201288.00 0.2 200773.00 201669.00 freed : 398712.00 0.1 398331.00 399227.00 freelist : 0.00 0.0 0.00 0.00 Back Close
  • 46. ObjectSpace.each object riddle 45/49 Can you explain the output of this script? def f (o) 1 1000.times { Array.new }; 1 2 end 3 4 puts ObjectSpace.each object { } 5 6 f (0) 7 8 puts ObjectSpace.each object { } 9 10 100.times do 11 puts ObjectSpace.each object { |o| f (o) } 12 end 13 Back Close
  • 47. config/benchmarks.rb 46/49 # create benchmarker instance 1 2 RAILS BENCHMARKER = RailsBenchmarkWithActiveRecordStore.new 3 4 # RAILS BENCHMARKER.relative url root = ’/’ 5 6 # if your session manager isn’t ActiveRecordStore, or if you don’t 7 # want sesssions to be cleaned after benchmarking, just use 8 # RAILS BENCHMARKER = RailsBenchmark.new 9 10 # create session data required to run the benchmark 11 # customize this code if your benchmark needs session data 12 13 require ’ user’ 14 RAILS BENCHMARKER.session data = {:user id => 23} 15 16 Back Close
  • 48. config/benchmarks.yml 47/49 default: uri: / all: default, empty, welcome, cat, letter empty: uri: /empty/index new_session: true welcome: uri: /welcome/index new_session: true letter: uri: /rezept/letter/G cat: uri: /rezept/cat/Hauptspeise query_params: page=5 Back Close
  • 49. Coding link to manually 48/49 page c1 real c2 real c1 r/s c2 r/s c1 ms/r c2 ms/r c1/c2 1: 1.38033 1.36467 724.5 732.8 1.38 1.36 1.01 2: 2.21867 2.32833 450.7 429.5 2.22 2.33 0.95 3: 2.90067 2.92733 344.7 341.6 2.90 2.93 0.99 4: 2.87467 2.77600 347.9 360.2 2.87 2.78 1.04 5: 11.10467 7.63033 90.1 131.1 11.10 7.63 1.46 6: 12.47900 6.38567 80.1 156.6 12.48 6.39 1.95 7: 12.31767 6.46900 81.2 154.6 12.32 6.47 1.90 8: 11.72433 6.27067 85.3 159.5 11.72 6.27 1.87 GC: c1 real c2 real c1 #gc c2 #gc c1 gc% c2 gc% c1/c2 6.48867 3.16600 43.0 23.0 11.38 8.76 1.87 • the relation c1/c2 depends on the hardware used. This seems to indicate that the quality of the Ruby implementation / OS memory management has a significant influence on relative performance. • you probably shouldn’t manually code every link_to. just use this method on pages with a large number of links. (Or wait for my template optimzer :-) Back Close
  • 50. Measuring GC Performance Using 49/49 railsbench perf_run_gc n quot;-bm=benchmark . . .quot; [data f ile] runs named benchmark, producing a raw data file perf_times_gc data f ile prints a summary for data in raw data file Back Close