This site is dedicated to further knowledge about creating Ruby on Rails applications professionaly. We discuss Ruby on Rails features from a performance angle, discuss Ruby on Rails performance analysis methods, provide information on Ruby on Rails scaling and benchmark Ruby on Rails performance for each release. We discuss best practices for selecting Ruby on Rails session containers, fragment and page caching and optimizing database queries.

French translation of Railsexpress articles

Posted 27 Dec 2005

Tremeur Balbous has translated some of my blog articles into French. You can find them on www.railsfrance.org.

This is great news, for me, and the French Rails community.

Merci beaucoup, Tremeur.

View Comments

Roll your own SQL session store

Posted 19 Dec 2005

The alert reader may have noticed that I'm using my own SQL session store, which provides much better performance than the default ActiveRecordStore shipping with Rails.

I have decided to publish the source code here. If you are using Mysql, simply unpack the files into your lib directory and make SQLSessionStore your session storage.

require 'sql_session_store'
require 'mysql_session'
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.
    update(:database_manager => SQLSessionStore)
SQLSessionStore.session_class = MysqlSession
If you're using components, which you probably shouldn't, you'll need to activate eager session saving:
MysqlSession.eager_session_creation = true

The improved performance is due to a number of factors:

  • fixed number of known DB columns
  • retrieve only fields into the session that are actually used to create the session for a controller
  • offloading most of the work to the DB, including updating the created_at and updated_at fields
  • hard coded Mysql statements

As a consequence, if you want another DB, other DB column names, don't want created_at or updated_at fields, you'll have to change the code.

I have uploaded HTML representations of the call trees for ActiveRecordStore and SQLSessionStore. If you inspect them closely, you'll see how much time ActiveRecordStore spends in just creating the SQL statements and how much simpler the call tree is for SQLSessionStore.

If you adapt the provided code for other database systems, I'd be happy if you sent me the code, and I'll add it to the download after reviewing. The required changes are probably pretty small, but I currently don't have the time to test other DB systems.

Enjoy!

View Comments

Rails 1.0 Release

Posted 18 Dec 2005

It's party time! Rails 1.0 hit the streets this week.

Somehow I didn't manage to release a performance report on the new release on the very same day, as planned ..., but here it is.

Rails 1.0 performs slightly worse than the previous 0.14.1 release for my application. However, 1.0 is still much faster than the 0.13 release series.

The following performance data table shows the speed difference for the fastest available configuration for the tested application.

page c1 totalc2 total c1 r/sc2 r/s c1 ms/rc2 ms/r c1/c2
/empty/index 1.261111.40676 793.0710.9 1.261.41 0.90
/welcome/index 1.418141.57333 705.1635.6 1.421.57 0.90
/rezept/index 1.500771.66533 666.3600.5 1.501.67 0.90
/rezept/myknzlpzl 1.493741.65309 669.5604.9 1.491.65 0.90
/rezept/show/713 3.599883.99798 277.8250.1 3.604.00 0.90
/rezept/cat/Hauptspeise 4.540244.86669 220.3205.5 4.544.87 0.93
/rezept/cat/Hauptspeise?page=5 4.647294.97066 215.2201.2 4.654.97 0.93
/rezept/letter/G 4.590544.84387 217.8206.4 4.594.84 0.95
 c1: 0.14.1, c2: 1.0, r/s: requests per second, ms/r: milliseconds per request

The reasons for this significant slowdown have been identified and are being worked on (tickets 3155 and 3174).

You can find additional information and lots of performance data in the full report.

View Comments

Trim your output

Posted 06 Dec 2005

The 0.14 Rails series includes a new option setting for template rendering, which allows for reducing the number of newlines generated by template processing. It's a string valued class attribute for ActionView, called erb_trim_mode. Its value is passed to the ERB compiler when a template gets compiled, with a default value of "-".

Some documentation for possible settings is part of the ERB class doc.

However, the doc is incomplete, as it doesn't mention Rails' default setting "-".

erb_trim_mode affects the way template processing handles newline characters in the template. Per default, (when erb_trim_mode is set to nil), processing leaves all newline characters occurring in the template in the generated html code. Which means that many extraneous newlines get inserted into your output.

For example,

<% if expr %>
some text
<% else %>
other text
<% end %>
will generate the following processing code:
if expr ; _erbout.concat("\n")
_erbout.concat("some text\n")
else ; _erbout.concat("\n")
_erbout.concat("other text\n")
end ; _erbout.concat("\n")

With the default setting of erb_trim_mode, you can suppress extraneous newline characters by adding a - before the closing %>:

<% if expr -%>
some text
<% else -%>
other text
<% end -%>
will generate the following template code:
if expr
_erbout.concat("some text\n")
else
_erbout.concat("other text\n")
end

This version looks much cleaner, suppresses 2 superfluous newline characters in the generated HTML code and saves 2 function calls when processed. Which is no big deal, unless the above call occurs inside a loop. If the loop body gets executed 100 times, you have already saved 200 characters and, more importantly, 200 function calls.

Manually adding all the minuses to closing %> markup is somewhat tedious. erb_trim_mode comes to rescue: if set to ">", newline characters will be suppressed for <%...%> markup closing a line; if set to "<>", newline characters will be suppressed for <%...%> occurring as a line of its own.

I have measured the relative performance of setting erb_trim_mode to ">". The following table shows that my app's pages receive a performance increase ranging from 1 to 4%.

configuration 1: 12-06.uncached.untrimmed
  requests=1000, options=-bm=uncached -lib=r141 -mysql_session
                         -fast_routes -fast_readers

configuration 2: 12-06.uncached.trimmed
  requests=1000, options=-bm=uncached -lib=r141 -mysql_session
                         -fast_routes -fast_readers -trim

page   c1 real   c2 real  c1 r/s  c2 r/s   c1 ms/r  c2 ms/r  c1/c2
 1:    3.52722   3.47518   283.5   287.8      3.53     3.48   1.01
 2:    4.30330   4.26213   232.4   234.6      4.30     4.26   1.01
 3:    4.49761   4.36027   222.3   229.3      4.50     4.36   1.03
 4:    4.45229   4.27840   224.6   233.7      4.45     4.28   1.04

urls:
 1: /rezept/show/713
 2: /rezept/cat/Hauptspeise
 3: /rezept/cat/Hauptspeise?page=5
 4: /rezept/letter/G

Unfortunately, ERB doesn't support combining the "-" and ">" setting. So you'll have to decide which way to go upfront. If you choose on ">", you may find that you have to add empty lines in some places where they weren't needed before.

View Comments

Don't load stuff you don't need

Posted 28 Nov 2005

Using Rails 0.14 and onward, you can give your app a slight performance boost by not loading parts of the framework that you don't need. For example, if you don't expose parts of your app as a web service, then you don't need to load actionwebservice. Likewise, if you don't send mail from your app, you don't need to load actionmailer. If you're using the Rails initializer to start your app, you can do it like so:
Rails::Initializer.run do |config|
  # Skip frameworks you're not going to use
  config.frameworks -= [ :action_web_service, :action_mailer ]
  ...
end
If you're still using an old environment.rb, just comment out the corresponding require lines:
# Require Rails libraries.
require 'active_support'
require 'active_record'
require 'action_controller'
# require 'action_mailer'
# require 'action_web_service'
Additionally, you should also load only the database adapters for the database(s) which you are using. Add the following to your environment.rb, before Rails gets required:
RAILS_CONNECTION_ADAPTERS = %w(mysql)
By default, Rails will load all connection adapters it can find. Minimizing your code footprint will speed up Rails, because Ruby traverses all abstract syntax trees stored on the heap during garbage collection. If you can avoid loading significantly sized code, you will reduce the memory footprint of your app, thereby speeding up garbage collection. It might also help to increase object lookup at runtime due to smaller sized data structures containing meta information.

View Comments

Older posts: 1 2 3 4 5 6 7 8 9