Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 Cli executes commands really slow?

somebody knows why my rails 3.0.7 cli is so slow? when i run rails s or rails g it takes like 5sec till he actually executes the command...

any advice? thanks

like image 499
trnc Avatar asked Jul 14 '11 06:07

trnc


1 Answers

Update: I'm switching my recommendation from rrails to rails-sh as the former supports REPL which is not the use case for rrails.Also patching does seem to add performance when combined with ruby environment variables, now reflected in the answer.


One possible reason may be this performance bug in ruby that has it call some code whenever "require" is used in the ruby code (more details here ). I ran in to this issue as well on my development box when developing with Rails (I use rails 3.2.6 on ruby 1.9.3p194 at the moment). The development environment runs on Ubuntu but this problem may happen on other operating systems because it's based on the interpreter.

While that bug is not fixed, there are two things I did to shave time from my ruby CLI. The first is to preload with rails-sh and the second is to use a popular ruby performance boosting patch to build an MRI ruby that is faster.

There are two libraries that do preloading nicely: rrails and rails-sh. Both are great but I will discuss rails-sh because it offers REPL support for commands like rails console in the terminal and binding.pry/debugger in the code.

Setup rails-sh

I put it in my development group since that's where I use rails/rake commands often and need speed.

group :development do
#...
  gem 'rails-sh'
end

Then install it :

bundle install --binstubs=./bundler_stubs

(I use binstubs to avoid 'bundle exec' in commands but that's optional)

Now just open a spare terminal to your rails project and run the rails-sh (add bundle exec if you need to):

$ rails-sh

.     ....    ...      ..  .......    ............    ...  ..  .
.  ..  ..  ..  ....  ....  ......  ..............  ......  ..  .
.     ...      ....  ....  .......    ...      ...    ...      .
.  ..  ..  ..  ....  ....  ..........  ..............  ..  ..  .
.  ..  ..  ..  ..      ..      ...    ............    ...  ..  .
................................................................
                                                         v1.5.2

# require /home/yuvilio/ws/site/config/boot
# require /home/yuvilio/ws/site/config/application
# Rails.application.require_environment!
Rails.env: development
type `help` to print help
rails-sh(site)>

Now you can use rake and rails command in that prompt

rails-sh(site)> rails s
$ rails s
=> Booting Thin
=> Rails 3.2.6 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
>> Thin web server (v1.4.1 codename Chromeo)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:3000, CTRL+C to stop

Or to run a rake task like db:test:prepare:

rails-sh(site)> rake db:test:prepare
12.471001136sec
rails-sh(site)> 

But is it fast? Well, on my machine (a core i5 laptop with 8gig RAM), the same rake db:test:prepare took 12.5 seconds inside the rails-sh command (see above) compared to 34 seconds without it:

$ time rake db:test:prepare
real  0m34.796s
user  0m21.057s
sys 0m1.144s
$

The 22 second difference was that the rake command outside rails-sh had to load the rails environment before getting to the database, which is wasteful since it hadn't changed. The same applies for rails commands.

Patched ruby

Another solution for MRI rubies, which is compatible with preloading and suggested in the rails performance guide, is to install a popular patch (falcon, railsexpress) on your ruby 1.9 and add some environment variables that use it.

I tested out the falcon and railsexpress patches (separately) on an rvm install and picked up similar performance in both cases.

$ rvm get head
$ rvm cleanup sources
$ rvm install ruby-1.9.3-p194 --reconfigure  --name falcon  --patch falcon --force-autoconf -j 3
$ rvm use ruby-1.9.3-p194-falcon

To make use of the patch

export RUBY_HEAP_MIN_SLOTS=1000000
export RUBY_HEAP_SLOTS_INCREMENT=1000000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_GC_MALLOC_LIMIT=1000000000
export RUBY_HEAP_FREE_MIN=500000

You can track which patches are available for which rubies in rvm here.

like image 147
12 revs Avatar answered Sep 28 '22 09:09

12 revs