Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline templates leak memory #35372

Closed
tenderlove opened this issue Feb 22, 2019 · 1 comment
Closed

Inline templates leak memory #35372

tenderlove opened this issue Feb 22, 2019 · 1 comment
Assignees

Comments

@tenderlove
Copy link
Member

I don't have a fix for this yet, but inline templates definitely leak memory.

Here is a test:

require "action_pack"
require "action_controller"
require "rack/utils"

class TestController < ActionController::Base
  def self.controller_path; "test"; end

  def index
    render inline: 'Methods: <%= methods.length %>'
  end
end

def send_request
  env = Rack::MockRequest.env_for("/",
                                  "REMOTE_ADDR"     => "0.0.0.0",
                                  "HTTP_USER_AGENT" => "Rails Testing",
                                 )

  request = ActionDispatch::Request.new(env)
  res = TestController.make_response!(request)
  controller = TestController.new
  str = ''
  controller.dispatch(:index, request, res).last.each { |x| str << x }
  str
end

puts send_request
10.times { |i|
  500.times { send_request }
  p i => send_request
}

If you run this script you'll see the number of methods on AV::Base increase. We use the object id to calculate a method name, so the leak isn't exactly linear as some object ids will get recycled:

$ be ruby a_controller_test.rb
Methods: 349
{0=>"Methods: 847"}
{1=>"Methods: 1337"}
{2=>"Methods: 1818"}
{3=>"Methods: 2290"}
{4=>"Methods: 2768"}
{5=>"Methods: 3232"}
{6=>"Methods: 3719"}
{7=>"Methods: 4197"}
{8=>"Methods: 4680"}
{9=>"Methods: 5154"}
@tenderlove tenderlove self-assigned this Feb 22, 2019
@tenderlove
Copy link
Member Author

This only impacts master, and I broke it by removing the finalizers. So I'll fix it.

tenderlove added a commit that referenced this issue Feb 23, 2019
This commit adds a finalizer just to inline templates.  We can't cache
compilation of inline templates because it's possible that people could
have render calls that look like this:

```ruby
loop do
  render inline: "#{rand}"
end
```

and we would cache every one of these different inline templates.  That
would cause a memory leak.  OTOH, we don't need finalizers on regular
templates because we can cache, control, and detect changes to the
template source.

Fixes: #35372
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant