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
Improve require
performance, particularly on systems with a lot of gems installed
#4951
Improve require
performance, particularly on systems with a lot of gems installed
#4951
Conversation
Thanks for opening a pull request and helping make RubyGems and Bundler better! Someone from the RubyGems team will take a look at your pull request shortly and leave any feedback. Please make sure that your pull request has tests for any changes or added functionality. We use GitHub Actions to test and make sure your change works functionally and uses acceptable conventions, you can review the current progress of GitHub Actions in the PR status window below. If you have any questions or concerns that you wish to ask, feel free to leave a comment in this PR or join our #rubygems or #bundler channel on Slack. For more information about contributing to the RubyGems project feel free to review our CONTRIBUTING guide |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome, thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's one spec failure that needs some tweaks in bundler to pass now.
Head branch was pushed to by a user without write access
I've applied another fix to solve CI failure on JRuby. 825d0e4 It works in my environment, but I'm not sure it is the right way. It cleans |
@pocke Your fix looks good to me. JRuby monkeypatches the |
Can you rebase and squash everything into one commit? |
I didn't know that. Thanks!
Sure, I'll do that 🚀 |
825d0e4
to
90c1919
Compare
…ion_missing_extensions_ Improve performance of Specification#missing_extensions? (cherry picked from commit 9b43650)
require
performance, particularly on systems with a lot of gems installed
This patch improves the performance of
Specification#missing_extensions?
method.What was the end-user or developer problem that led to this PR?
missing_extensions?
is slow, because it callsdefault_gem?
method and it allocatesString
instances.What is your fix for the problem, implemented in this PR?
I benchmarked
require 'rails'
, then I found a bottleneck aboutmissing_extensions?
.Note that there are many gems (
gem list | wc -l # => 481
) in my environment.Profilings
Gem::Specification#missing_extensions?
takes 6.4% ofrequire 'rails'
, anddefault_gem?
takes 4.4%.Because
default_gem?
allocates two String instances withFile.dirname(loaded_from)
andGem.default_specifications_dir
.I confirmed it with
memory_profiler
gem.How to fix
I've fixed this problem with two solutions.
First, swap
default_gem?
andextensions.empty?
order.Previously
missing_extensions?
first calleddefault_gem?
, thenextensions.empty?
. Butextensions.empty?
is faster thandefault_gem?
because it just callsArray#empty?
. So I swapped them to avoid callingdefault_gem?
method ifextensions.empty? == true
.Second, cache
Gem.default_specifications_dir
. It depends onGem.default_dir
butGem.default_dir
is also cached. So I think cachingGem.default_specification_dir
is no problem too.Micro Benchmark
5x faster 🚀
Real-world benchmark
1.059x faster 🚀
Make sure the following tasks are checked