Skip to content
New issue

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

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

Already on GitHub? # to your account

Optimize memory alloc and retained #2441

Merged
merged 9 commits into from
May 20, 2024

Conversation

ericproulx
Copy link
Contributor

@ericproulx ericproulx commented May 18, 2024

This PR should improve memory allocation and retained.

Base code

class API < Grape::API
  prefix :api
  version :v1, using: :path

  namespace :test do
    2000.times do |index|
      get "/test#{index}/" do
        'hello'
      end
    end
  end
end

MemoryProfiler.report(allow_files: 'grape') do
  API.compile!
end.pretty_print

This code

branch allocated retained
master ~85.2 MB (502079 objects) ~15.74 MB (80035 objects)
this branch ~75.34MB (408047 objects) ~13.08 MB (54028 objects)
Difference ~9.96 MB (94032 objects) ~2.66 MB (26007) objects)

Real world app

branch allocated retained
master ~64.16 MB (353932 objects) ~9.02 MB (26379 objects)
this branch ~61.44 MB (329231 objects) ~5.86 MB (15271 objects)
Difference ~2.72 MB (24701 objects) ~3.17 MB (11108) objects )

Improve caching

lib/grape/namespace.rb and lib/grape/path.rb were already caching but it could be improved by adding Grape::Router.normalize_path call directly in the cache instead.

Stringify inheritable settings

prefix,namespace and other inheritable settings may be naturally declared with a symbol instead of a string and along compilation, they will be stringified and join create more complex strings. Saving them as string saves some memory allocation.

delete_if instead of -

delete_if will remove elements in the array and returns it. Substracting two arrays will create a new one. Most cases were calling keys and substracting values from its.

Replace AttributesTranslator by ActiveSupport::OrderedOptions

AttributesTranslator is basically a hash with dynamic accessor methods and it is used in lib/grape/router/route.rb and lib/grape/router/greedy_route.rb. These 2 also have an options which is the same data included in the AttributesTranslator. It didn't make sense to keep these two. So, I found that ActiveSupport::OrderedOptions is literally a hash with dynamic accessor methods and it could replace entirely AttributesTranslator. In conjunction with delegate_missing_to, I've successfully drop AttributesTranslator and just add an alias attributes to options.

Introducing base_route.rb

lib/grape/router/greedy_route.rb and lib/grape/router/route.rb are vey close in terms of code so I've created a base_route that both would inherit. It also encapsulated the regexification. I've also added some cache for the regex captures.

Some small refactors

I've refactored some small functions.

Fix #2440

@dblock
Copy link
Member

dblock commented May 20, 2024

This looks good. I opened #2442, too, might take it up if I have some time.

@ericproulx ericproulx marked this pull request as ready for review May 20, 2024 15:52
@dblock dblock merged commit 7c3ff27 into ruby-grape:master May 20, 2024
44 checks passed
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Investigation memory allocations
2 participants