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

Fix memory leak caused by caching all unique paths seen #2084

Merged
merged 1 commit into from
Jul 10, 2020

Conversation

fcheung
Copy link
Contributor

@fcheung fcheung commented Jul 10, 2020

I recently updated one of our apps from grape 1.2.5 to 1.3.3 and have observed a memory leak. After analysing some heap dumps taken from our app I believe I have tracked this back to part of the changes in #2002

The change to router.rb caches normalized paths here: https://github.com/ruby-grape/grape/blob/master/lib/grape/router.rb#L10

This retains indefinitely every path that flows through grape. We have a number of apis where the path is of the form foo/bar/id/action where id is the id of the object the api call is acting on, so this grows in a more or less unbounded way.

Since this was just a memory optimization, I would suggest just reverting that part of the changes in #2002 which is what this PR does

@grape-bot
Copy link

grape-bot commented Jul 10, 2020

1 Warning
⚠️ There’re library changes, but not tests. That’s OK as long as you’re refactoring existing code.

Generated by 🚫 danger

Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes ouch. Care to fix CHANGELOG please, I'll merge.

CHANGELOG.md Outdated
@@ -6,6 +6,7 @@
* [#2060](https://github.com/ruby-grape/grape/pull/2060): Drop support for Ruby 2.4 - [@dblock](https://github.com/dblock).
* [#2060](https://github.com/ruby-grape/grape/pull/2060): Upgraded Rubocop to 0.84.0 - [@dblock](https://github.com/dblock).
* [#2077](https://github.com/ruby-grape/grape/pull/2077): Simplify logic for defining declared params - [@dnesteryuk](https://github.com/dnesteryuk).
* [#2084](https://github.com/ruby-grape/grape/pull/2084): Fix memory leak in path normalization- [@fcheung](https://github.com/fcheung).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space before -

@dblock dblock mentioned this pull request Jul 10, 2020
@dblock
Copy link
Member

dblock commented Jul 10, 2020

Also cc: @ericproulx you'll want to take a look at this.

This optimisation was introduced in ruby-grape#2002. If an api's paths include
an id in the path then this cache can grow in an unbounded manner.
@fcheung
Copy link
Contributor Author

fcheung commented Jul 10, 2020

Thanks - I have fixed changelog. Running 1.3.3 + this patch on one of our hosts at the moment & memory usage seems stable enough.

@ericproulx
Copy link
Contributor

ericproulx commented Jul 10, 2020

I don't mind reverting. I'll try to find a way to keep the most unique api calls instead of just adding all of them. Creating a kind of LRU policy but inside a ruby hash.
https://github.com/SamSaffron/lru_redux

@dblock dblock merged commit b2bc98d into ruby-grape:master Jul 10, 2020
terrchen pushed a commit to terrchen/gitlab that referenced this pull request Jul 17, 2020
@dnesteryuk dnesteryuk mentioned this pull request Jul 20, 2020
dslh pushed a commit to dslh/grape-jr that referenced this pull request Jul 22, 2020
Besides upgraded Grape, it changes the response body for 204 HTTP status,
now it is an empty string instead of an empty hash.

Rack introduced lazy body initialization (rack/rack@8c62821)
which only works with strings. However, when 204 HTTP status is returned, Grape
doesn't stringify the response (https://github.com/ruby-grape/grape/blob/master/lib/grape/middleware/formatter.rb#L27-L29),
thus, a hash is returned as a response body. `Rack::MockResponse` fails with

    TypeError (no implicit conversion of Hash into String)

It could be a bug in the JsonAPI resources gem, why does it return an empty hash
for 204 HTTP status?!. Definetly, it isn't a bug in Grape, nor Rack.
The logic for formatting the reponse body in Grape hasn't changed for 5 years.

The main motivation for this upgrade is a fix for memory leak
ruby-grape/grape#2084
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

Successfully merging this pull request may close these issues.

4 participants