Skip to content

Conversation

@amatsuda
Copy link
Member

This patch drastically reduces time taken to load the gem in all non-Windows platforms by bypassing the versioned .so require attempt that is necessary only for binary gems.

On my local Mac machine, requiring psych gem became 5x faster with this patch (this may change depending on number of gems being installed there).

ruby -e "now = Time.now; gem 'psych', '3.1.0'; require 'psych'; p '3.1.0' => Time.now - now"
ruby -e "now = Time.now; gem 'psych', '3.1.1'; require 'psych'; p '3.1.1' => Time.now - now"

{"3.1.0"=>0.186081}
{"3.1.1"=>0.037546}

I guess we actually achieved a huge ✌️, because almost everyone using Ruby on Linux, Mac, and such gets 150ms-ish speed up for free on some Ruby-made command execution, like gem install, rails, etcetc.

This excellent idea was implemented by @nobu for io-console gem, and already included in its 0.4.8 release.
ruby/io-console#4

@eregon
Copy link
Member

eregon commented Jul 14, 2019

The gain sounds nice.

Is there a reason to use this "stub" technique?
It seems quite obscure to me and I don't really understand what it does.
https://github.com/ruby/io-console/pull/4/files seems much easier to understand and more straightforward.

Finally, do you think this is something that should maybe be solved in RubyGems, by e.g., maintaining an index of all require-able files so there is no need to search for which file for a given require?

Is the reason of this versioned require that binary gems contain precompiled extensions for multiple versions of Ruby in the same binary gem?
Maybe there should be one binary gem per Ruby version.

@amatsuda
Copy link
Member Author

Is there a reason to use this "stub" technique?
It seems quite obscure to me and I don't really understand what it does.
https://github.com/ruby/io-console/pull/4/files seems much easier to understand and more straightforward.

The "stub" technique is indeed super tricky, but it's more accurate than my initial patch there.
Gem.win_platform? at the runtime is not an exact condition for finding the platforms that may contain versioned .so file.
OTOH @nobu's approach is to inject a requirable stub file when actually building a binary gem, which should 100% be correct.

Finally, do you think this is something that should maybe be solved in RubyGems, by e.g., maintaining an index of all require-able files so there is no need to search for which file for a given require?

I do agree that it's nicer if RubyGems can handle this more elegantly. But I'm not sure if "index of all require-able files" would even be possible where we have to deal with autoload, multi-threads, etc.

Is the reason of this versioned require that binary gems contain precompiled extensions for multiple versions of Ruby in the same binary gem?
Maybe there should be one binary gem per Ruby version.

Right. That could solve this particular problem, but it may add other costs for the maintainers, such as release management or version numbering.

@eregon
Copy link
Member

eregon commented Jul 15, 2019

OK, thank you for the explanation, that makes sense.
I will suggest to add some comments to explain how this works in the changed files.

@amatsuda
Copy link
Member Author

@eregon Thank you for reviewing! Just added the comments!

@hsbt hsbt mentioned this pull request Jul 21, 2019
@hsbt hsbt closed this in #408 Jul 21, 2019
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.

2 participants