-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Reduce allocations in Gem::BUNDLED_GEMS.warning?
#13727
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
base: master
Are you sure you want to change the base?
Reduce allocations in Gem::BUNDLED_GEMS.warning?
#13727
Conversation
lib/bundled_gems.rb
Outdated
segments = feature.split("/") | ||
segments = feature.split("/", 3) |
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 branch needs to have three segments at most.
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.
Do you know why it only needs 3 segments at most? I don't doubt it, but it's not obvious (to me) from the code why that is. I think a comment explaining the number would be helpful.
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.
Ah, because only two shifts. 🤦
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.
Yes two shifts and then just one needed for the segments.any?
return value. I'll add a comment 👍🏽
name = [name, segments.shift].join("-") | ||
name = "#{name}-#{segments.shift}" |
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.
While I was here I thought I'd eliminate this array allocation. This was only showing up at around 0.5%, but why not 🤷🏽♂️
Actually I did just confirm this. Without bootsnap, I see many features like |
b454ef5
to
0d779a1
Compare
lib/bundled_gems.rb
Outdated
@@ -105,11 +105,14 @@ def self.warning?(name, specs: nil) | |||
# and `require "syslog"` to `require "#{ARCHDIR}/syslog.so"`. | |||
feature.delete_prefix!(ARCHDIR) | |||
feature.delete_prefix!(LIBDIR) | |||
segments = feature.split("/") | |||
# 1. A segment for the basic EXACT and SINCE check e.g. `logger` | |||
# 2. A segment for the multi-part SINCE check e.g. `resolv-replace` |
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.
I don't think that resolv-replace, which provides resolv-replace.rb
as the name says, is the targets of this code.
The targets are net/* family, net-http gem for require "net/http"
.
I suspect that this code can be removed since such libraries are no longer in SINCE
table.
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 code" is joining the first two segments with -
.
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.
Thanks, I've removed that and updated the comments. I also had to remove a failing test for net/smtp
. I think I can also remove this one?
ruby/spec/bundled_gems_spec.rb
Lines 347 to 364 in eab4a0b
it "Don't show warning with net/smtp when net-smtp on Gemfile" do | |
build_lib "net-smtp", "1.0.0" do |s| | |
s.write "lib/net/smtp.rb", "puts 'net-smtp'" | |
end | |
script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s } | |
gemfile do | |
source "https://gem.repo1" | |
path "#{lib_path}" do | |
gem "net-smtp" | |
end | |
end | |
require "net/smtp" | |
RUBY | |
expect(err).to be_empty | |
end |
It passes, but it's probably a false positive now.
As well as the SINCE
entry here?
ruby/spec/bundled_gems_spec.rb
Line 66 in eab4a0b
Gem::BUNDLED_GEMS.const_set(:SINCE, { "openssl" => RUBY_VERSION, "fileutils" => RUBY_VERSION, "csv" => "3.4.0", "net-smtp" => "3.1.0" }) |
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.
I've gone ahead and removed them.
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.
@hsbt What do you think? Or we should keep the feature?
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.
I don't want to remove these tests.
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.
Okay I've put all of that back and kept the comments example-free, given the spec has good examples.
66e2039
to
b7bb0ab
Compare
This comment has been minimized.
This comment has been minimized.
b7bb0ab
to
9cf6b95
Compare
When profiling our (@buildkite's) Rails application's boot, this
String#split
consistently showed up as taking 3-4% of allocation samples (~125k+ allocations) with a sample rate of 100. I suspect this may be related to our use of bootsnap given the comments in this method, though I haven't tested without it to confirm.Unfortunately I can't share that specific a profile, but I tried to compare profiles using a micro test script
Viewer: https://vernier.prof/ - filter data source to allocations and invert call tree stack
~70% fewer allocations
I didn't open an issue for this, but I did come across https://bugs.ruby-lang.org/issues/20641, so it seems this method is known to be somewhat of a hotspot.