Nick Sieger: RailsConf: Stefan Kaes - Rails Performance http://blog.nicksieger.com/articles/2006/06/23/railsconf-stefan-kaes-performance en-us 40 "RailsConf: Stefan Kaes - Rails Performance" by Nick <p>Heh, yeah, maybe it&#8217;s about time for me to get off my rear end and customize my typo so it doesn&#8217;t look like every other typo blog out there, including railsexpress&#46;de!</p> Sun, 13 Aug 2006 17:06:51 +0000 urn:uuid:34aa829a-7857-4ac1-a9ba-48bcd9fa1dec http://blog.nicksieger.com/articles/2006/06/23/railsconf-stefan-kaes-performance#comment-47 "RailsConf: Stefan Kaes - Rails Performance" by Yan <p>bleh, my bad, I thought this was stefan&#8217;s blog :)</p> Fri, 11 Aug 2006 22:33:35 +0000 urn:uuid:f3ef53b0-7342-4994-b2a6-1a0bfb5077af http://blog.nicksieger.com/articles/2006/06/23/railsconf-stefan-kaes-performance#comment-46 "RailsConf: Stefan Kaes - Rails Performance" by Yan <p>Hi Stefan,</p> <p>any news on the template optimizer? Sounds like a really interesting and valuable idea&#46; I am very concerned with rails performance in the views&#46;&#46;thanks!</p> Fri, 11 Aug 2006 22:33:04 +0000 urn:uuid:5b6659a0-bec4-4774-9df5-a03c764944c2 http://blog.nicksieger.com/articles/2006/06/23/railsconf-stefan-kaes-performance#comment-45 RailsConf: Stefan Kaes - Rails Performance <p>Stefan starts by citing a factor of 4&#45;5 improvement in performance in Rails over the last year&#46;</p> <h2>Performance, broken down</h2> <ul> <li>Latency &#45;&#45; how fast</li> <li>Throughput &#45;&#45; how many</li> <li>Utilization &#45;&#45; how idle is the cpu</li> <li>Cost efficiency &#45;&#45; performance per unit cost</li> </ul> <p>For completeness calculate the min, max, mean and standard deviation of these metrics and use the deviation as your guide for how reliable the data is&#46;</p> <h2>Tools</h2> <ul> <li>Log files (level > <code>Logger::DEBUG</code>)</li> <li><a href="http://rails-analyzer.rubyforge.org/">Rails Analyzer Tools</a> (Eric Hodel)</li> <li>Benchmarker (<code>script/benchmarker</code>)</li> <li>DB vendor tools</li> <li>Apache bench (<code>ab</code> or <code>ab2</code>)</li> <li>httperf</li> <li><a href="http://rubyforge.org/projects/railsbench">railsbench</a> (Stefan Kaes)</li> </ul> <h2>Railsbench</h2> <p>Railsbench measuress raw performance of rails request processing&#46; It&#8217;s configured using <code>config/benchmarks.yml</code> and <code>config/benchmarks.rb</code>&#46; These files let you control which requests get benchmarked, whether to create a new session when benchmarking them, etc&#46;</p> <h2>Profiling Tools</h2> <ul> <li>Ruby Profiler</li> <li>Zen Profiler</li> <li>rubyprof</li> <li>Rails profiler script</li> <li><a href="http://www.softwareverify.com/rubyPerformanceValidator/index.html">Ruby Performance Validator</a></li> </ul> <p>At this point Stefan gave an overview of RPV, which appears to be a nifty tool that lets you get typical hotspot tree views of where time is spent in code&#46; It currently only runs on Windows&#46;</p> <h2>Top Rails Performance Problems</h2> <ul> <li>slow helper methods</li> <li>complicated routes</li> <li>associations &#45;&#45; navigating and eager loading vs&#46; proxy loading</li> <li>retrieving too much data from the DB</li> <li>slow session storage (e&#46;g&#46;, ActiveRecord store)</li> </ul> <p>Stefan says that in his experience, DB performance is generally not a big factor or bottleneck&#46; Instantiating ActiveRecord objects is expensive, though&#46;</p> <h2>Session containers</h2> <ul> <li>In memory &#45;&#45; if you server crashes&#46;&#46;&#46;oops&#46; Also doesn&#8217;t scale&#46;</li> <li>File system &#45;&#45; easy to set up, scales with NFS, but slower than&#46;&#46;&#46;</li> <li>ActiveRecordStore &#45;&#45; easy to set up since it comes with Rails, but much slower than&#46;&#46;&#46;</li> <li>SQLSessionStore &#45;&#45; which uses the same table structure as ActiveRecordStore, but was written by Stefan to overcome performance issues with ActiveRecordStore&#46; Setup is more involved&#46;</li> <li>memcached &#45;&#45; slightly faster than SQLSessionStore, scales best, but setup is also more involved&#46;</li> <li>DrbStore &#45;&#45; distributed ruby store</li> </ul> <h2>Caching</h2> <ul> <li>Full pages &#45;&#45; fastest, complete pages are served on the filesystem&#46; Web server bypasses appserver for rendering&#46; If you have private pages, you can&#8217;t use it&#46;</li> <li>Actions &#45;&#45; pages are cached after an action is rendered&#46; The user ID can be used as part of the storage key&#46;</li> <li>Fragments &#45;&#45; fragments can be cached in memory, on the file system, in a DrbStore, or in memcached&#46; Memcached scales the best but doesn&#8217;t support expiring fragments by regular expression&#46;</li> </ul> <h2>ActionController</h2> <ul> <li>Stefan recommends avoiding components, and replacing them with helpers or partials&#46; He has not found a use for them&#46;</li> </ul> <h2>ActionView</h2> <ul> <li>Don&#8217;t create unnecessary instance variables in the controller; creating them in the view with <code>instance_variable_set</code> and accessing with <code>instance_variable_get</code> is slow&#46;</li> </ul> <h2>Helpers</h2> <ul> <li>pluralize &#45;&#45; don&#8217;t use the inflector if you don&#8217;t need to, it&#8217;s expensive&#46;</li> <li>link<em>to and url</em>for are among the slowest helpers, since they need to use routes&#46; Instead, if you have page with lots of links, you might consider hard&#45;coding the links&#46; This reduces the amount of GC by up to 50% and the GC time down by a few percentage points (11&#46;3% to 8&#46;7% of total processing time)&#46;</li> </ul> <h2>ActiveRecord</h2> <ul> <li>use the <code>:include</code> option to prefetch associations, it avoids extra onesy&#45;twosy SQL statements&#46;</li> <li>use piggy&#45;backing plugin for <code>has_one</code> or <code>belongs_to</code> relationships &#45;&#45; allows you to retrieve extra attributes from additional tables in the same fetch query&#46;</li> <li>Field values are retrieved from the DB mostly as strings, so type conversion happens on each access, which can be slow&#46;</li> </ul> <h2>Language&#45;level and miscellaneous issues</h2> <ul> <li>Method calls are the slowest &#45;&#45; don&#8217;t needlessly create method abstractions</li> <li>Short&#45;circuit intermediate results to improve performance</li> <li>Cache results in instance variables or class variables</li> <li>Don&#8217;t call <code>ObjectSpace.each_object</code> on each request</li> </ul> <h2>Ruby Memory Management</h2> <ul> <li>designed for batch scripts, not long&#45;running servers&#46;</li> <li>no generational garbage collection&#46;</li> <li>this is suboptimal for Rails because ASTs are stored on the heap (biggest portion of non&#45;garbage for Rails apps), and get processed/traversed more often than they need to be</li> <li><a href="http://rubyforge.org/projects/railsbench">Railsbench</a> includes a patch to allow one to recompile Ruby and tweak the garbage collector&#46;</li> </ul> <h2>Rails Template Optimizer</h2> <ul> <li>Stefan has started a project to &#8220;compile&#8221; templates&#46;</li> <li>The idea is to cache results of some ERb scriptlets and essentially &#8220;compile&#8221; or replace the template with one that has more expressions expanded or inlined&#46;</li> <li>Code forthcoming; I assume you can stay tuned to <a href="http://railsexpress.de/blog/">Rails Express</a> for news&#46;</li> </ul> <h2>Questions</h2> <ul> <li>There was a question on JRuby &#45;&#45; Stefan replied that it would certainly solve GC issues, but he doesn&#8217;t know if it&#8217;s in a state to be able to benchmark Rails requests&#46;</li> <li>What are your recommendations for a web server&#46; <em>I don&#8217;t have any&#46;</em></li> <li>Is horizontal or vertical scaling better? <em>I don&#8217;t know, I&#8217;ve been focused on making single requests go fast, so I don&#8217;t have enough experience&#46;</em></li> </ul> Fri, 23 Jun 2006 20:40:00 +0000 urn:uuid:032b3183-e579-4896-a439-2f62ee8279e6 Nick Sieger http://blog.nicksieger.com/articles/2006/06/23/railsconf-stefan-kaes-performance ruby rails railsconf http://blog.nicksieger.com/articles/trackback/24