RSS RailsExpress.blog

http://railsexpress.de/blog/

How to make your rails app run reeeeeally fast!

Last checked 31 minutes ago.

14 people have subscribed to this feed.

Feed frequency

post frequency (last month)

PostRank™ filter

latest 15 posts

« older items




Wednesday January 23rd, 2008

1.0

Ruby/Rails Consultants wanted

RailsExpress.blog From RailsExpress.blog, 11 months ago, 0 comments Comment

I need 2 additional consultants for the Rails CRM project I’m managing for Autoscout24.

It’s a massive Rails application with 198 models and 60 controllers. A large part of the code base consists of business logic.

Requirements:

  • brightness
  • ability to get things done
  • willingness to dive into an existing code base, fix stuff and extend existing functionality
  • good social skills
  • ability to speak English (German is a plus)

If you’re interested, send me your credentials.

The contract duration would be 6 months initially.

This is an on site project in Munich, telecommuting is unfortunately not possible.

Friday December 28th, 2007

3.0

Writing Efficient Ruby Code - Short Cut

RailsExpress.blog From RailsExpress.blog, 1 year ago, 0 comments Comment

This has been a busy year for me, but I have finally managed to complete the first chapter of my book “Performance Rails” and Addison Wesley has published it as a digital short cut .

It’s a collection of performance patterns (and anti patterns) which I have successfully applied to speed up the Rails framework. I hope you will find it useful.

Tuesday September 18th, 2007

5.2

Rails Edge Performance

RailsExpress.blog From RailsExpress.blog, 1 year ago, 0 comments Comment

Listening to David's RailsConf Europe 2007 keynote, I've learned that he's going to a release a beta version soonish. He's asked me to do some benchmarking, comparing the performance of edge Rails to the latest stable branches. Here's a chart:

stable11 is the current svn version of branch 1-1-stable, stable12 is current version of 1-2-stable branch and edge is the current version of Rails trunk. Numbers are requests per second (measured on my MacBook during David's talk).

If you're a numbers type, these are the numbers:

page c1 totalc2 total c1 r/sc2 r/s c1 ms/rc2 ms/r c1/c2 empty 0.947091.05049 1055.9951.9 0.951.05 0.90 welcome 1.228781.34536 813.8743.3 1.231.35 0.91 recipes 1.372141.50364 728.8665.1 1.371.50 0.91 my_recipes 1.369581.49912 730.2667.1 1.371.50 0.91 show 3.469444.27918 288.2233.7 3.474.28 0.81 cat 3.726754.58788 268.3218.0 3.734.59 0.81 cat_page5 3.856244.68700 259.3213.4 3.864.69 0.82 letter 3.699704.54140 270.3220.2 3.704.54 0.81 all requests 19.6697123.49406 406.7340.5 2.462.94 0.84 GC statistics c1 totalc2 total c1 #gcc2 #gc c1 gc%c2 #gc% c1/c2 2.276573.09640 21.025.0 11.5713.18 0.74

c1: 1.2-stable, c2: edge, r/s: requests per second, ms/r: milliseconds per request

I haven't had time to analyze the code, but it seems that anything loading a large number of active record objects takes a rather large performance hit.

I hope we can improve performance before 2.0 gets finally released. Unfortunately, I have almost no time to work on this. However, if anyone has a performance patch, I can look into the it.

Wednesday June 6th, 2007

1.0

Rails Consultant wanted

RailsExpress.blog From RailsExpress.blog, 1 year ago, 0 comments Comment

I’m looking for an experienced Rails consultant to complement the team working for Autoscout24 on the International Sales Synergy Project which I am managing.

Requirements:

brightness ability to get things done willingness to dive into an existing code base, fix stuff and extend existing functionality good social skills ability to speak English (German is a plus)

If you’re interested, send me your credentials.

Sunday April 1st, 2007

New Railsbench Release (0.9.2)

RailsExpress.blog From RailsExpress.blog, 1 year ago, 0 comments Comment

A new version of railsbench has been released. Benchmarking POST requests is now supported, benchmark specific session data can be specified in the benchmark config file and ERB can be used as well.

added POST support:
    search:
      uri: /search
      method: post
      post_data: category=dessert
method defaults to getpost_data will be url encoded by railsbench   allow specification of session_data in benchmarks.yml:
    benchmark_name:
      uri: /
      session_data:
         user_id: 1
      post_data: category=dessert
  load benchmarks.yml using ERB. Example: retrieve login ids using Rails)
    admin_interface:
      uri: /admin
      session_data:
        user_id: <%= User.find_by_name('admin').id %>
  use benchmark names instead of urls in raw data files, old files can be converted using script convert_raw_data_files. change was required by post support   copy environments/production.rb to environments/benchmarking.rb, instead of providing a fixed one   don’t create a broken benchmarks.yml file when running railsbench install   perf_plot and perf_plot_gc accept -geometry parameter, for exact dimensioning of the produced .png file   use -font_size=12 for setting font size when generating graphs   use ‘perf_plot -colors=color1,color2,...’ to get a different color set   use ‘perf_plot -out=name’ to write graph to file ‘name’   new script perf_table: create a tabular overview of perf data   added -colorize option to perf_html, which results in green and red backgrounds in the factor columns   added -theme option to perf_plot

Happy benchmarking!

Rails 1.2 Performance

RailsExpress.blog From RailsExpress.blog, 1 year ago, 0 comments Comment

Rails 1.2-stable is somewhat slower than Rails 1.1-stable, especially on action cached pages. But the slowdown I measured is nowhere near the numbers which have been reported by others. In fact, two recent patches to speed up session creation and pstore session retrieval, have resulted in improved performance for one of the benchmarked actions.

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

page c1 totalc2 total c1 r/sc2 r/s c1 ms/rc2 ms/r c1/c2 empty 11.4403410.91962 437.0457.9 2.292.18 1.05 welcome 13.0464814.29709 383.2349.7 2.612.86 0.91 recipes 10.8361713.51635 461.4369.9 2.172.70 0.80 my_recipes 10.8013713.48035 462.9370.9 2.162.70 0.80 show 24.1672227.37878 206.9182.6 4.835.48 0.88 cat 26.5603829.88683 188.3167.3 5.315.98 0.89 cat_page5 27.2495430.78081 183.5162.4 5.456.16 0.89 letter 26.9906730.17507 185.2165.7 5.406.04 0.89 all requests 151.09216170.43488 264.7234.7 3.784.26 0.89 GC statistics c1 totalc2 total c1 #gcc2 #gc c1 gc%c2 #gc% c1/c2 10.4279012.90426 120.0135.0 6.907.57 0.81

Read the full report here.

Sunday January 14th, 2007

Railsbench gem updated

RailsExpress.blog From RailsExpress.blog, 1 year ago, 0 comments Comment

Today I’ve released a new gem version (0.9.1) of railsbench. It’s mainly a bug fix release for the installation problems discovered for 0.9.0.

However, there’s also a new script called generate_benchmarks, which can be used to generate and maintain the benchmark configuration file used by railsbench.

railsbench generate_benchmarks updates the benchmark configuration file with

a benchmark for each controller/action pair (named <controller>_<action>) a benchmark for each controller combining all actions of the controller into one benchmark (named <controller>_controller) a benchmark comprising all controllers (named all_controllers)

This should get you started benchmarking in no time ;-)

After generating the file, you will need to edit the benchmarks and replace routing placeholders (:id, :article_id, etc.) by actual values.

If you add new controllers/actions later in the development process, you can invoke railsbench generate_benchmarks again to add new items to the configuration file. The older entries will not be removed by this process.

Currently, generate_benchmarks only works for the 1.2 release candidate and edge Rails (but I’ll gladly accept patches to make it work with 1.1.6).

Happy benchmarking!

Tuesday December 26th, 2006

Producing Performance Graphs

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

The latest version of railsbench contains scripts to convert raw performance data files into pretty pictures. They depend on rmagick and gruff to be installed on your system.

railsbench perf_plot <files>

will generate a chart comparing benchmark data from all files passed as arguments.

Example:

Enjoy!

railsbench gem version available

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

railsbench is now available as a gem from RubyForge. I recommend all users to switch to the gem version. This move should make it much easier to maintain railsbench installations for a larger number of machines.

Installation is now as simple as sudo gem install railsbench. Or, if you have installed the 0.8.4 gem version: sudo gem update railsbench.

The gem release will install only one ruby driver script, named railsbench in the default ruby path; individual commands like perf_run etc. are accessible through this driver. So instead of typing

perf_run 100 "-bm=all -mysql_session" 

you would use

railsbench perf_run 100 "-bm=all -mysql_session" 

The perf_ command prefix is now optional, thus

railsbench run 100 "-bm=all -mysql_session" 

would give identical results.

If you’re accustomed to the old syntax and find typing railsbench awkward, you could add the gem’s script directory to your search path, by adding the following code to your shell profile:
eval `railsbench path`; export PATH

This will continue to work should you upgrade railsbench to a newer version.

Update: In order to call the scripts directly, you need to issue a sudo railsbench postinstall command after installing the gem. I haven’t found a way to create a gem that sets the executable bit on anything which lives outside the bin directory and isn’t a binary executable.

Friday November 10th, 2006

On Premature Optimization

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

The alert reader of my blog might have noticed that I really care about performance. Some people even have accused me of being “obsessed” with it. Very often these statements are accompanied by Tony Hoare’s famous line: “Premature optimization is the root of all evil.”, which was later repeated by Donald Knuth.

I’ve always admired the work of Hoare and Knuth and I’m well aware of the famous quote on premature optimization. And they’re absolutely right: premature optimization is evil.

However, what lots of people seem to miss out, is that the most important word in his statement is “premature”.

If you don’t give any consideration to performance, you will be sure to avoid premature optimization. But you might have made a design decision which simply cannot be reverted without huge cost at a later stage of the project.

Let me give you an example: I once was asked to evaluate a project because it had performance problems. The software was intended to be used in a call center, which requires really fast response times. It turned out that the external company hired to implement this software, had made the decision to write the UI dialogs in a custom templating language, for which they had written an interpreter. The interpreter had been written in Visual Basic, which, at that time, was an interpreter as well.

So in effect, the dialogs were running c1*c2 times slower than necessary, where c1 and c2 are the interpreter overheads. It’s probably safe to assume the software ran about 25-50 times slower than necessary. And even top of the line hardware with 2 processors wasn’t able to make the package run fast enough.

In the end, the whole project was canceled, after pouring millions of EUR into it. And the problem was solved by buying another call center wholesale. I still believe today, that if some consideration had been given to performance questions during the architectural design phase, this disaster could have been avoided.

So, yes, premature optimization is evil, but no consideration for performance issues is just as bad.

Update: BTW, I was prompted to write this little piece after reading a blog entry about a talk delivered at the Web 2.0 conference. It clearly shows that speed matters down to sub second resolution, even for web applications. I wouldn’t be surprised, if a well known UI axiom gets proven to hold in web context as well: response time should be below 100ms for graphical user interfaces. Making it faster is almost unnoticeable to the end user, but slower than 100ms does have negative effects.

Thursday November 9th, 2006

SqlSessionStore gains support for SQLite

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

Ted X Toth has submitted the code for a SQLite session class implementation for SqlSessionStore. I have checked it into the subversion repository.

Thank you very much Ted!

Thursday October 5th, 2006

Make ruby-mysql create less garbage

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

During the preparation of my RailsConf2006 talk I did some comparative benchmarks with Mysql and Postgresql. To my astonishment, I observed that Rails with Mysql created many more objects. After digging into the C part of ruby bindings of Mysql, I discovered that the Mysql bindings create a copy of the columns name string for each record retrieved from the database. This obviously leads to quadratic memory use and calls for correction.

I’ve written a small patch for the ruby-mysql bindings and submitted it to the author, but never got a response, although a tried several times.

You can get the patch here.

The patch actually goes a little farther than just correcting the n*m problem. I have added a Mysql::Result.all_hashes method, so that the entire array of hashes creation runs in C.

For pages that retrieve small datasets, you will probably see only a small increase. I measured around 5% increase for pages that load 25 objects. Which is neat. But the patch really shines when you retrieve large data sets. For example, for loading 1000 objects, I got this perf data:

page c1 totalc2 total c1 r/sc2 r/s c1 ms/rc2 ms/r c1/c2 /alphabetic 6.861265.20610 14.619.2 68.6152.06 1.32 GC statistics c1 totalc2 total c1 #gcc2 #gc c1 gc%c2 #gc% c1/c2 2.142501.18728 24.012.0 31.2322.81 2.00

30% faster!

But more important, a lot less gargabe gets created (in the example GC runs twice as often with the unpatched bindings).

You can take advantage of this by creating your own garbage ;-)

Oracle support for sql_session_store

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

Due to a contribution from Tiago Macedo, sql_session_store has gained Oracle support.

If you’re on Oracle and want improved session handling performance, you should give it a try.

If you find any problems, please submit bug reports/patches here.

And if you now how to and have time to implement support for other database adapters, please send an email or better, create a ticket and attach the patch.

Saturday September 23rd, 2006

New plugin: query_builder

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

I’ve added another plugin for you to check out: query_builder.

This plugin enables you to define finder methods that bypass the overhead of construct_finder_sql.

Inside an ActiveRecord model definition,
  define_finder query_name, query_type, options_hash
will create a SQL query method called query_name from a given options_hash. query_type can be :first or :all. The plugin supports all options except :include, but ignores with_scope options. Example:
class Recipe
  define_finder :find_all_of_user, :all,
     :conditions => 'user = :user AND priv < :priv'
  end
This defines a query method which can be called like so:
Recipe.find_all_of_user :user => 'martin', :priv => 1
This call is equivalent to
Recipe.find :all, :conditions =>
            [ 'user = :user AND priv < :priv',
              {:user => 'martin', :priv => 1} ]
If options[:positional] is not nil or false, the created query method will use positional paramaters instead of a hash. In this case, arguments are created in the order of appearance on the parameters passed to define_finder. Therefore
define_finder :find_all_of_user, :all,
      :conditions => 'user = :user AND priv < :priv',
      :positional => true
will create a query method with parameters user and priv, which can be called like so:
Recipes.find_all_of_user('martin', 1)

I converted one of my pages to use this style and it gained 10% more performance.

If you like this plugin, drop me a line. If you find a bug, please submit a bug report to Trac

Enjoy.

Saturday September 16th, 2006

Piggy back plugin updated

RailsExpress.blog From RailsExpress.blog, over 2 years ago, 0 comments Comment

Timo Hentschel, one of my coworkers at the company for which I’m doing contract work at the moment (AutoScout24), has added a nifty little extension to my piggy_back plugin.

It’s now possible to piggy back from has_many :through associations, provided the association will return at most one record from the underlying SQL query.

This type of association currently needs to be used as a replacement for the non existent has_one :through.

There have been rumours that has_one :through will find it’s way into rails core. If it does, I’ll probably remove the has_many :through support from piggy back plugin again, or at least raise a deprecation warning.

« older items