Rails memory leak: controller class containing instance reference

I have a memory leak in a Rails 4.2.6 application. The controller allocates the large object GaragesPresenteras an instance variable to be deleted and garbage collected after the request is complete. However, I see that this never happens.

def show
  @garage = GaragesPresenter.new(@garage, view_context)
  respond_to do |format|
    format.html
  end
end

I see that the reference to the instance GaragesPresenteris stored by the instance GaragesController, and the instance is stored by this class GaragesController. This is true after the request is completed and GC.start. Why GaragesControllerdoes the class contain an instance reference?

I know this because I set the heap heap with:

require 'objspace'
...
GC.start
file = File.open("/tmp/dumpfile", 'w')
ObjectSpace.dump_all(output: file)

And in the resulting file, I see the following three objects:

The next object is GaragesPresenter, which is very large:

{"address":"0x7fd077217e20", "type":"OBJECT", "class":"0x7fd074a04618", "ivars":7, "references":["0x7fd0772bf940", "0x7fd077711480", "0x7fd077748188", "0x7fd077772898", "0x7fd07720c778", "0x7fd0771ef8d0", "0x7fd0771ef8d0"], "file":"/Users/dyoung/workspace/commutyble/site-app/app/controllers/garages_controller.rb", "line":19, "method":"new", "generation":35, "memsize":56, "flags":{"wb_protected":true, "old":true, "marked":true}}

GaragesController (, show ):

{"address":"0x7fd0727559f0", "type":"OBJECT", "class":"0x7fd0727865a0", "ivars":22, "references":["0x7fd0727558b0", "0x7fd072755888", "0x7fd072755838", "0x7fd0732400e0", "0x7fd072754a50", "0x7fd0734c5658", "0x7fd07704e878", "0x7fd0732ab020", "0x7fd072785ee8", "0x7fd077217e20", "0x7fd0771ffe10", "0x7fd07720cde0", "0x7fd0732a82d0"], "file":"/Users/dyoung/.rvm/gems/ruby-2.1.0/gems/actionpack-4.2.6/lib/action_controller/metal.rb", "line":237, "method":"new", "generation":35, "memsize":176, "flags":{"wb_protected":true, "old":true, "marked":true}}

GaragesController GaragesController, . ??

{"address":"0x7fd0727865a0", "type":"CLASS", "class":"0x7fd0726a7260", "name":"GaragesController", "references":["0x7fd0727559f0", "0x7fd0726a72b0"], "file":"/Users/dyoung/.rvm/gems/ruby-2.1.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb", "line":435, "method":"instance_exec", "generation":35, "memsize":672, "flags":{"wb_protected":true, "old":true, "marked":true}}

+4
2

WeakRef

Reference, . A WeakRef , .

foo = Object.new

foo = WeakRef.new(foo) # Creates a weak reference to orig

ObjectSpace.garbage_collect

p foo.to_s       # should raise exception (recycled)

. , . , -. ( ) , , . .

. , , perl. ++ . (), . , , , . - " ". - .

- . , -, .

+3

GaragesPresenter view_context

@garage = GaragesPresenter.new(@garage, view_context)

view_context , self, :

# File actionview/lib/action_view/rendering.rb, line 71
def view_context
  view_context_class.new(view_renderer, view_assigns, self)
end
+1

Source: https://habr.com/ru/post/1669088/


All Articles