Joyent

Translations of this page:

How to reduce the memory footprint of your rails app

Some of Jason's numbers

Don't fall into the trap of premature optimization. Wait until you have reached a major milestone(s) in your development before bothering to tune. See the section at the bottom about ActiveRecord tips and tricks you should keep in mind as you develop the codebase.

Pre-flight

  • Well just how much am I using?
  • Freeze your rails into vendor. I cannot stress this enough, make your rails application as insulated from the deployed environment as possible. If you don't freeze your rails, you cannot take advantage of the removing unused frameworks below …
  • gem unpack your gems into vendor/gems
  • Just how much memory does my account have?

Environment.rb

  • remove unused frameworks.
  # Skip frameworks you're not going to use (only works if using vendor/rails)
  config.frameworks -= [ :action_web_service, :action_mailer ]

Cache and what it means to me

Learn the differences between, and how to use, page, action and fragment caching by purchasing this screencast from Peepcode.com for $9:

http://peepcode.com/products/page-action-and-fragment-caching

I found it really useful.

"Too many open files" errors

By default, there's a limit of 256 open file descriptors at any time. This is very easy to hit with a good sized rails app and will cause (at least a mongrel cluster) to die with a fail-safe error 500.

To fix this, you need to increase the limit on file descriptors for the running processes. You can do this by one of the following methods:

  1. run `ulimit -n 1024` in your SMF, before starting your app
  2. run
    plimit -n 1024,65536 [pid of running process]

    after the server is running.

  3. Add
    Process.setrlimit(Process::RLIMIT_NOFILE, 1024, 65536)

    to your environment.rb to increase the resource limits at runtime.

ActiveRecord tips and tricks

FAT models, THIN controllers. Write that finder method. Trust me you will thank me in the morning.

  • ActiveRecord is smart, but don’t do:
    • write a JOIN query
      Post.find(:all).each do |p|
       
       p.subscribers << @user unless p.subscribers.include?(@user)
       
      end

Remember that SQL is an ultimate and highly effective weapon, and ActiveRecord is very talky with the database. The less requests to the database the faster it works.

I don’t know if it relevant but for me using reject with AR objects has led to enormous memory consumption (looks like the objects being reject’ed from the enumerable were not garbage collected)

  • pull all records into memory just to throw some away
    Post.find(:all).reject{|p| p.comments_closed? }

    better to use

    Post.find(:all, :conditions=>"comments_closed = 0")
     
    #or do
    Post.find_all_by_comments_closed(false)
    #or write the specialized finder method in model.

FAT models, THIN controllers. I know I'm violating the DRY here … but this _is_ worth repeating.

How to find those expensive calls

Don't fret over every line in your model. Better to spend the time optimizing the calls which are used 1000 times then once a week. So how do you find those calls? Analyze your *production* logs That is right, take the time to optimize the calls your *users* make the most.

 
accelerators/tuning_rails.txt · Last modified: 2008/04/05 06:47 by filip
 
Recent changes RSS feed Creative Commons License Driven by DokuWiki