19

I can't figure out why my Rails app (hosted on Heroku (cedar)) keeps allocating more and more memory. If I didn't know any better I'd say that this a memory leak in Ruby/Rails, but since I'm completely new to Ruby/Rails, I feel like I'm missing something completely obvious.

I'm using Rails defaults generated by rails new, and completely up-to-date gems:

source 'https://rubygems.org'

gem 'rails', '3.2.8'

group :development do
  gem 'sqlite3'
end

group :assets do
  gem "sass-rails", "~> 3.2.5"
  gem "coffee-rails", "~> 3.2.2"
  gem "uglifier", "~> 1.3.0"
end

gem "jquery-rails", "~> 2.1.2"

group :production do
  gem 'newrelic_rpm'
  gem "pg", "~> 0.14.1"
end

I'm using the default newrelic config. I have zero models and one controller, nothing_controller.rb, which was generated using rails generate controller nothing:

class NothingController < ApplicationController
  def index
  end
end

I deleted public/index.html and added an empty views/nothing/index.html.erb. The only other thing I did to the generated app was add a route to routes.rb:

Nothing::Application.routes.draw do
  root :to => "nothing#index"
end

I committed, pushed it to Heroku, then wrote a quick script that would load my Heroku page every 10 seconds. This is what my New Relic reports:

https://i.stack.imgur.com/cbm4k.png

That's all there is to it. Memory just keeps increasing like that until it passes Heroku's limit of 512MB. The code in this app is pretty much the same as the code I've seen in the tutorial I followed. I don't understand what I'm doing wrong.

Any guidance would be greatly appreciated.

EDIT (9/12): In case it's relevant, I'm using ruby 1.9.

Code I'm using to hit the server (C#):

using (var wc = new WebClient())
  for (;; Thread.Sleep(10000))
    wc.DownloadString("http://vast-earth-9859.herokuapp.com/");

EDIT (9/13): Going to try disabling New Relic and seeing if it still R14s.

user1650177
  • 445
  • 3
  • 10
  • Seeing the code that hits your server every 10s would be nice. – deefour Sep 13 '12 at 00:12
  • Sure. Added. As a side note, the reason I decided to do this was because a fairly basic app I wrote had the some problem and would run out of memory after ~400 page views. – user1650177 Sep 13 '12 at 00:20
  • Try adding Oink to monitor what's getting instantiated. RubyProf may take some finagling, but if you can get it to work, that would provide more insight. Generally, memory is supposed to increase -- this is good. Additionally, it's supposed to be garbage collected when it is not used as often. – maletor Sep 13 '12 at 05:31
  • I can run Oink fine locally (each request says `Instantiation Breakdown: Total: 0`, as expected) but I can't figure out how to use it on Heroku. Logs aren't stored in logs/* and a cursory Google search did not tell me much. I don't get it though...is something wrong with my Rails or something? I feel like I'm the only one with this problem. How does everyone else's heroku+rails apps not run out of memory? – user1650177 Sep 13 '12 at 06:21
  • You definitely seem to have a weird problem. Forward this to heroku support. – maletor Sep 13 '12 at 18:02
  • And post the solution here when you find out! – maletor Sep 14 '12 at 18:56
  • On it. First going to let this empty app R14. – user1650177 Sep 14 '12 at 22:27
  • 1
    What version of newrelic gem is in your Gemfile.lock? THere were some memory issues a while back, which may be resolved by running bundle update newrelic or manually specifying the latest version of the gem. – jakeonrails Sep 19 '12 at 19:27
  • 2
    Sorry for the late response. Have had nearly no free time lately. jakeonrails was correct. After updating newrelic with bundle update my rails apps no longer run out of memory. They still go up to ~300MB, at which point they drop back down. – user1650177 Oct 02 '12 at 08:29

2 Answers2

5

Trying removing newrelic gem. I had have same issue on heroku and culprit was newrelic gem. You can check your current object that is memory. Below code show you the object count.

ObjectSpace.each_object.with_object(Hash.new(0)){|obj, h| h[obj.class] +=1 }.select{|k,v| puts "#{k} => #{v}" if k == String || k == Array || k == Hash}
MKumar
  • 1,524
  • 1
  • 14
  • 22
2

Once the memory exceeds(512 MB) the limit on heroku, it won't get the memory down immediately by restarting the app or by changing code. It will keep on growing and slows it further, heroku itself kills the process when it hits heroku's memory threshold (not sure how much it is).

There are various things might have caused the memory leaks, following are the few 1. Continuous exceptions thrown 2. Getting lot of data in a single request.

Testing it on local machine won't help since you won't have any memory restriction on your machine.

Do the following to see the heroku log and figure what are the latest errors what are items take time.

heroku logs -a <application name> -n<number of lines>

Stop the application for day or so then you can the change code and start the application.

Sethupathi
  • 930
  • 9
  • 9