Skip to content
This repository

Memory Leak in Development Mode #170

Closed
tkieft opened this Issue June 06, 2011 · 48 comments
Tyler Kieft
tkieft commented June 06, 2011

Every time I load a new page I get more objects in memory of these classes: (discovered using ObjectSpace.each_object)

ActiveAdmin::
Resource
Scope
DSL
ActionItems
Resource::BelongsTo
PageConfig
ControllerAction
Namespace
Menu

I dug around in the code trying to figure out why this was happening, but couldn't find an explanation :( Wonder if this is happening for everyone or just me.

Philippe Creux
Collaborator
pcreux commented June 06, 2011

Sadly, this is happening for everyone. :-/

We were thinking that this could happen when reloading the classes. The profiling tools developped by @tmm1 could help http://en.oreilly.com/rails2011/public/schedule/detail/18051. We didn't find a chance to work on that yet. Any contribution is welcome! :)

Greg Bell
Owner

Yeah this is something we definitely want to fix. Haven't had a chance to take a look at it yet

Vijay Dev

Any timeline in mind for this one?

Ernesto Rocha

Do you guys are experiencing this on production environment too ?

It seems only test environment is ok to me.

Ryan T
ryanto commented July 02, 2011

Ernestorocha,

Development environment is where it leaks... that is to say, any environment where cache_classes is set to false there will be a pretty big memory leak when using active admin.

I'd like to publicly +1 this ticket, been following it for a while.

edit: dump typo!

Manu J
Collaborator
j-manu commented July 04, 2011

It is a problem in development mode because the memory consumed crosses 500 MB quite fast and the development machine slows down especially when I'm running a VM.

Manu J
Collaborator
j-manu commented July 05, 2011

Memprof dump from a sample app: http://bit.ly/jsEhxs (takes some time to load everything).

References to various ResourceControllers are not being released.

For the time being I modified Active Admin to not unload the resources (http://bit.ly/pfG1Xd) . This stops the memory leak with the caveat that you will have to reload your Active Admin models if you are working on them. This is not a problem for me because, the Active Admin part of the app is largely done but the memory leak was affecting the entire development work.

Ernesto Rocha

Recently I was experiencing some strange memory growth on my production server. The first suspect was the active admin, but after some test and research I discovered it was rails 3.0.7! Just to help who will debug the memory leak of active admin, don't do this on rails 3.0.7. I downgraded the version to 3.0.4 and the memory stabilized. Thanks for this great tool!

Code Brew Studios

Any updates on this issue? I've recently setup active admin, it works great and is super flexible for our needs. However, this issue has slowed down my dev environment to a crawl and for the time being I've had to disable active admin.

Ryan T

Codebrew, in your config/development.rb add this at the end of the file

# dont reload active admin classes in dev mode.  
module ActiveAdmin
  class Reloader
    def attach!
    end
  end
end

That will prevent the active_admin classes from reloading. There's a catch though, you'll have to restart your rails server every time you make a change to an active admin file... or you can just comment out the above and let the memory leak while you are editing your admin files. Both situations sucks, but hopefully you won't be editing your admin files too much.

Jon Frisby

The problem here is that every time ActiveAdmin reloads itself, it re-registers with ActionDispatch but does not UNregister the previous instance. Thus, ActionDispatch maintains references to the full chain of ActiveAdmin classes/objects for all previous requests and never releases them.

It gets worse: Since all copies are still registered, all copies receive each request notification, and attempt to reload. The end result is that number of ActiveAdmin reload operations becomes O(n^2), for n requests.

You can observe this by instrumenting the code thusly:

module ActiveAdmin
  class Reloader
    def attach!
      STDERR.puts ">>>>>>>>>>>>>>>>>>>   ATTACH!"
      reloader_class.to_prepare do
        STDERR.puts ">>>>>>>>>>>>>>>>>>>   RELOAD!"
        ActiveAdmin.application.unload!
        Rails.application.reload_routes!
      end
    end
  end
end
Jon Frisby

Incidentally, in Rails 3.0.x at least (don't know about 3.1.0 as I'm not mucking with it just yet), the fix is to give to_prepare a symbol that identifies the block, allowing it to replace the reference instead of just accruing references:

module ActiveAdmin
  class Reloader
    def attach!
      reloader_class.to_prepare(:active_admin) do
        ActiveAdmin.application.unload!
        Rails.application.reload_routes!
      end
    end
  end
end
Dale Hofkens

with rails 3.1.0 this gives the following error on startup :
.rvm/gems/ruby-1.9.2-p290-patched/gems/activesupport-3.1.0/lib/active_support/callbacks.rb:413:in '_run_prepare_callbacks': undefined local variable or method 'active_admin' for #<ActionDispatch::Reloader:0x00000129cb3228 @app=nil> (NameError)

Jon Frisby

Ah, it seems this mechanism went away in 3.1. I'm submitting a pull request to use to_prepare without the identifier symbol, but to keep a state flag that avoids the duplicated registrations.

Jon Frisby

Pull request submitted: #466

Philippe Creux
Collaborator
Oleg Shparber

@MrJoy, just tried your fixes with 3.1.0 app, but unfortunately they don't fix mem leak for me...

Jon Frisby

@trollixx: As long as the change doesn't cause worse behavior in 3.1, I'd suggest landing it for now. I will dive into Rails 3.1 behavior once I'm updating our app to 3.1, which will hopefully be soon -- but won't be for at least a week unfortunately.

Gareth Bradley

The change suggested by @ryanto seems to help with page load times cutting them from some 6-13 secs to around 2 secs. I'm using rails 3.1

Rasmus

@ryanto's change to prevent the active_admin classes from reloading lowered the page load times in my 3.1 project as well.

Josef Šimánek simi referenced this issue from a commit October 10, 2011
Commit has since been removed from the repository and is no longer available.
HughGrant

I tried everything metioned on this page, but still memory leaks. And I wonder when would this bug fixed.

Sam Vincent

A solution that would work for me would involve ignoring reloading for requests that don't involve ActiveAdmin. I suppose that's kind of difficult since it reloads everything before processing the request.

Huan Son

anyone ?

Josh Pigford

Another vote for this. I've tried the mentioned fixes without luck.

Running Rails 3.0.6 and Ruby 1.9.2p290.

Danny Hiemstra

@gregbell merged my fix regarding sass asset compilation on every request into the new gem released today (0.3.4).
Could the people that have this problem update their activeadmin to this version and see if they still encounter this problem?

Joe Lind

This fixed our issue on 3.1.1. Thanks.

Ian MacLeod

@dhiemstra Object growth for ActiveAdmin:: objects has stopped, but old copies of model classes are hanging around indefinitely.

I've got a test case up at https://github.com/nevir/active-admin-leaks-sample

The activeadmin branch is a bare bones project w/ 0.3.4 set up - the migrations on this branch create a user for you (admin@admin.com / 123456). The vanilla branch of that repo is a clean rails project w/ a quick dashboard at root.

On the activeadmin branch, each refresh adds a new instance of the model class, and you can see a lot of the baggage from old ones hanging around (callbacks, etc)

Edit: added a devise branch to test it in isolation, as well (no leak)

eLod

the change introduced by ef255e5 still has some issues: i have cancan integrated with activeadmin and everything works as expected on 0.3.2, however on 0.3.3 activeadmin doesn't reload its own files, thus the resource configurations are referring to the old model classes (before the reload) [that is what @nevir mentioned i believe] and can? fails for the old classes (because its rules are already targeting the new classes). to be clear i created an extension that is automatically checking can?(:read, class) when deciding whether to render a menu (menu_item_display_if) and i'm simply reading the class from the configuration (e.g. ActiveAdmin::Resource#resource) which gives the old class.

Gordon DuQuqesnay

Until this is resolved is there an easy way to disable active admin in dev? I've tried setting a config variable

if ACTIVE_ADMIN_ENABLED
  require 'activeadmin' 

  ActiveAdmin.setup do |config|
.
.
.

This works for disabling it but when I turn it on I get this error:
/home/pair/.rvm/gems/ruby-1.8.7-p330@rails3/bundler/gems/active_admin-223ead429495/lib/active_admin/application.rb:214:in `initialize': wrong number of arguments (2 for 0)

Ian MacLeod

@gduquesnay set up your Gemfile so that it doesn't load active admin in the default or development groups

jaywengrow

Any updates on this issue? We love Active Admin, but it's wreaking havoc on our production server's memory.

Manu J
Collaborator
j-manu commented May 31, 2012

Which version are you on ? In the newer versions I have not come across the leak.

jaywengrow

We're on Active Admin 0.3.4 and Rails 3.0.1 - is that too old?

Manu J
Collaborator
j-manu commented May 31, 2012

Try the 0.4.x. A couple of commits were made to fix this. Not sure which versions they landed in

Ian MacLeod
nevir commented May 31, 2012

Edit: I spoke too soon

Just bumped https://github.com/nevir/active-admin-leaks-sample up to rails 3.2.3 & active admin 0.4.4 - the dev-mode leak is still present (touch an active admin file like the dashboard or one of your models, and all your old controller & model classes are hanging around)

Manu J
Collaborator
j-manu commented May 31, 2012

@nevir is the memory usage increasing per request?

Ian MacLeod
nevir commented May 31, 2012

Yes, every time you modify a source file in dev mode & the reloader kicks in, there is a reference to the class pre-reload hanging around (so you end up with multiple instances of your classes. AR walks them on each request, so it's more of a slow down than just GC time, too)

Ian MacLeod
nevir commented May 31, 2012

I haven't had a chance to dig into the AA code recently, but I think there are a few places where you're directly hanging onto class objects and not cleaning them up on reload

dapbot
dapbot commented May 31, 2012

+1 to this issue - I'm experiencing it on production server (heroku). I'm using active_admin 0.4.4 and rails 3.1.3.

Heroku produces an error message saying the process is requiring more than 512 Mb memory.

Manu J
Collaborator
j-manu commented May 31, 2012

@dapbot That's weird. AA leaked memory only in development mode. Did you try your app without AA?

dapbot
dapbot commented May 31, 2012

@j-manu Oh really? I was following @jaywengrow 's comment above that said it was wreaking havoc on their production server.

The problem only occurs when using AA to browse through my users index, so don't think there is a way to test by removing AA? Perhaps I'm doing something else wrong - apologies if I am leading the thread astray.

Manu J
Collaborator
j-manu commented May 31, 2012

@dapbot I meant that was not seen originally. The memory leak occurred because activeadmin was reloading classes in development mode but was not unloading previously loaded stuff. Many of us worked around this issue by disabling that. Since classes are not reloaded in production, this was not a problem in production.

If you can try to reproduce it with a minimal app, it would be great

Michael Elfassy

+1
I'm also getting 504 errors (timeouts) when trying to list users in AA (similar to @dapbot) with AA 0.4.4 and rails 3.2.3.
This is happening in production on EC2.

jaywengrow

I don't know if this is helpful for anyone - but I've found that removing certain filters helped a LOT for some of my models. Some filters, namely the select menu ones, were loading WHOLE tables (like SELECT * FROM USERS) to create select menu filters for objects associated with the model. Not a memory leak per se, but it's extremely memory intensive and can easily cause timeouts.
Also, keep in mind that when you don't define any filters, Active Admin gives you EVERY filter, including possibly these memory intensive ones. So define just the filters you need and make sure that they're not loading entire tables.

Bipen Sasi

+1 @jaywengrow - thanks for the above comment! it improved my app loading time tremendously!!

hsadan
hsadan commented July 26, 2012

+1 @jaywengrow - thanks! solved my problem.

James McKinney jpmckinney closed this August 22, 2012
James McKinney
Collaborator

Merged #1571. Please open new issues if new memory issues arise.

Matt Scilipoti

+1 @jaywengrow - thanks for the above comment! Limiting my Filters improved my app tremendously!! It looks like a good work-around for the runaway cpu/memory issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.