-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
Possible memory leak in prepend_view_path #14301
Comments
If I render the partial like: <%= render 'site_overrides/j-14.com/posts/shared/featured', post: post %> I don't see the issue. |
It looks like it is the string for the method name that is leaking If I change
to
I no longer the partials memory leaks. I seem to only get the main template method name leak:
|
Changing
to
Seems to fix my template leak problem |
Turns out, |
Even thought he I dumped the Using the class method in an initializer vs instance method in a before filter: https://gist.github.com/r38y/9400923 The difference I noticed is using the class method resulted in exactly the same instances for each of the objects but the instance method version resulted in different instance methods for
I think it makes sense (maybe) but I don't think the strings associated with them are being released. |
I've just noticed the same issue in my app with prepend_view_path and you saved me a lot of time by saying that it can be put it in an initializer, I didnt even think of it somehow :) Hope they'll fix it |
I'm glad it helped a bit! I have quite a few overrides depending on the request so the way I got around it was to create a registry in the initializer: PATH_SET_REGISTRY = {}
Dir.entries('app/views/site_overrides').reject{|e| e.in?(['.', '..'])}.each do|domain|
paths = ["app/views/site_overrides/#{domain}"]
PATH_SET_REGISTRY[domain] = ActionView::PathSet.new(paths)
end
PATH_SET_REGISTRY And then look up the override paths in that registry on each request:
I still think there is a memory leak in Rails because I think we should be using the same path and cache instances for each lookup path between requests. |
cc @tenderlove |
Can you prove the objects are actually being leaked by putting this code in an infinite loop and showing unbounded memory growth? Also a sample app would really help. |
I created a fresh, small app that has one action with prepend_view_path and one that doesn't: https://github.com/r38y/prepend_view_path_example
I used apache bench to hit it a bunch of times and it seemed like the one grew more than the other one, BUT, it is hard to see when the templates are so small. Our app is ~huge. Maybe someone can help me figure out how to get more info from it? |
What version of Ruby are you using? Also, does it require that you use apache, or do you see the same leak on different web servers? FWIW, I'm running with trunk Ruby and using WEBrick in production mode. I see large swings in memory usage, but it isn't growing unbounded. |
This issue has been automatically marked as stale because it has not been commented on for at least The resources of the Rails team are limited, and so we are asking for your help. If you can still reproduce this error on the Thank you for all your contributions. |
This issue has been automatically closed because of inactivity. If you can still reproduce this error on the Thank you for all your contributions. |
I confirm this issue. testable env:
|
The problem is that ActionView::PathSet is generated for each request and results in a memory leak. If you cache the response from ActionView::OptimizedFileSystemResolver then there is no problem using prepend_view_path. The Rails Guides currently recommends setting prepend_view_path pr request with a string that leads to this problem. I had a major memory leak in my app and setting a cached ActionView::OptimizedFileSystemResolver into prepend_view_path solved the issue. See also https://www.spacevatican.org/2019/5/4/debugging-a-memory-leak-in-a-rails-app/ |
@espen good point. Can you open a PR to change the guide to set the view path to a cached Resolver instance instead of a string? |
While using a persistent Resolver instance also fixed a memory leak for me, I would caution that it is causing issues when Action View caching is disabled (e.g. in development mode). Whenever I update a template, I get an I'm not sure what the right thing to do in this case is other than only using a persistent Resolver when Action View caching is enabled (falling back to using a SUBDOMAIN_SPECIFIC_TEMPLATES = {
'subdomain1' => ActionView::OptimizedFileSystemResolver.new('app/views/subdomain1'),
'subdomain2' => ActionView::OptimizedFileSystemResolver.new('app/views/subdomain2'),
'subdomain3' => ActionView::OptimizedFileSystemResolver.new('app/views/subdomain3')
}.freeze
def prepend_subdomain_specific_templates
subdomain_specific_templates = SUBDOMAIN_SPECIFIC_TEMPLATES.fetch(request.subdomain)
subdomain_specific_templates.clear_cache unless ActionView::Resolver.caching?
prepend_view_path(subdomain_specific_templates)
end |
Having the exact same issue as @mudge after upgrading a rails app to v6. We have a I looked into trying to figure out how to hook into the cache clear events to clear those too in addition to the resolvers that rails creates, but couldn't figure out how to wire that up. Clearing on every request in development mode works though. |
Hey @scottwillson , how did you remove it from your app ? It seems that I'm facing the same issue but I'm not sure on how to remove it 🤷 Simply removing the lines is obviously breaking the app, I would be interested to know how you did exactly ? 🙏 |
@DumasOlivier I realized in my app that I didn't need to do this per-request, so I switched to:
I also have a custom view handler for CMS-style pages:
I guess that might be less efficient that file-based templates, but it's not slow, and more important: doesn't leak memory. |
@scottwillson thank you I will try it then 🙏 |
Thanks for all this research. We also found this leak recently, and built a drop-in patch from the hints here and in this blog post. Find our patch at https://makandracards.com/makandra/515345-rails-fixing-the-memory-leak-in-prepend_view_path. Maybe related: #22580 |
I think I'm seeing a memory leak when using
prepend_view_path
.When I use the instance method in a controller:
I get a lot of leaked strings (and other objects in the same area)
That look like
_app_views_site_overrides_j____com_posts_shared__featured_html_erb___3233500999093705389_70234272758740
.When I use the class method in an initializer:
I don't leak anything in template.rb.
I need to use the instance method because I need to set things up for themes.
I've seen this in production and development.
This is how I'm getting that information: https://gist.github.com/r38y/02f4378a19f9064d2da2
I've been in the Rails source code for a couple days and cannot figure out why it is leaking 😦. Any ideas would would a ton. Thank you!
The text was updated successfully, but these errors were encountered: