diff options
author | Samuel Giddins <segiddins@segiddins.me> | 2023-09-14 19:34:15 -0700 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2023-09-15 17:54:01 +0000 |
commit | c423d6e0e48bd8a94548ff7a6275d93ae770f9d1 (patch) | |
tree | 1da67385319147d91714bf0ba78ebca410a45fb6 /lib | |
parent | 4d86d932fdbe91e436a5680ffae2f4db1a23b3be (diff) |
[rubygems/rubygems] Stop allocating the same settings keys repeatedly
Running `bundle update --bundler` on a rails app locally:
```
==> memprof.after.txt <==
Total allocated: 301.90 kB (3794 objects)
Total retained: 73.24 kB (698 objects)
==> memprof.before.txt <==
Total allocated: 14.47 MB (196378 objects)
Total retained: 25.93 kB (202 objects)
```
So for a slight increase in retained memory (all keys are now retained),
we go from about 200k allocations in the settings file to under 4k
https://github.com/rubygems/rubygems/commit/e64debb6ae
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bundler/settings.rb | 54 | ||||
-rw-r--r-- | lib/bundler/yaml_serializer.rb | 13 | ||||
-rw-r--r-- | lib/rubygems/yaml_serializer.rb | 13 |
3 files changed, 54 insertions, 26 deletions
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index 92b4a6a4e3..d14ce40dc4 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -97,6 +97,8 @@ module Bundler @global_config = load_config(global_config_file) @temporary = {} + + @key_cache = {} end def [](name) @@ -312,7 +314,7 @@ module Bundler end def key_for(key) - self.class.key_for(key) + @key_cache[key] ||= self.class.key_for(key) end private @@ -344,12 +346,12 @@ module Bundler end def is_bool(name) - name = name.to_s + name = self.class.key_to_s(name) BOOL_KEYS.include?(name) || BOOL_KEYS.include?(parent_setting_for(name)) end def is_string(name) - name = name.to_s + name = self.class.key_to_s(name) STRING_KEYS.include?(name) || name.start_with?("local.") || name.start_with?("mirror.") || name.start_with?("build.") end @@ -365,11 +367,11 @@ module Bundler end def is_num(key) - NUMBER_KEYS.include?(key.to_s) + NUMBER_KEYS.include?(self.class.key_to_s(key)) end def is_array(key) - ARRAY_KEYS.include?(key.to_s) + ARRAY_KEYS.include?(self.class.key_to_s(key)) end def is_credential(key) @@ -392,7 +394,7 @@ module Bundler end def set_key(raw_key, value, hash, file) - raw_key = raw_key.to_s + raw_key = self.class.key_to_s(raw_key) value = array_to_s(value) if is_array(raw_key) key = key_for(raw_key) @@ -412,7 +414,7 @@ module Bundler end def converted_value(value, key) - key = key.to_s + key = self.class.key_to_s(key) if is_array(key) to_array(value) @@ -472,17 +474,16 @@ module Bundler valid_file = file.exist? && !file.size.zero? return {} unless valid_file serializer_class.load(file.read).inject({}) do |config, (k, v)| - new_k = k - if k.include?("-") Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \ "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)." - new_k = k.gsub("-", "___") + # string hash keys are frozen + k = k.gsub("-", "___") end - config[new_k] = v + config[k] = v config end end @@ -512,7 +513,7 @@ module Bundler def self.key_for(key) key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http") - key = key.to_s.gsub(".", "__") + key = key_to_s(key).gsub(".", "__") key.gsub!("-", "___") key.upcase! @@ -536,5 +537,34 @@ module Bundler end "#{prefix}#{uri}#{suffix}" end + + # This is a hot method, so avoid respond_to? checks on every invocation + if :read.respond_to?(:name) + def self.key_to_s(key) + case key + when String + key + when Symbol + key.name + when Bundler::URI::HTTP + key.to_s + else + raise ArgumentError, "Invalid key: #{key.inspect}" + end + end + else + def self.key_to_s(key) + case key + when String + key + when Symbol + key.to_s + when Bundler::URI::HTTP + key.to_s + else + raise ArgumentError, "Invalid key: #{key.inspect}" + end + end + end end end diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb index d5ecbd4aef..6e4b44848f 100644 --- a/lib/bundler/yaml_serializer.rb +++ b/lib/bundler/yaml_serializer.rb @@ -54,8 +54,8 @@ module Bundler str.split(/\r?\n/).each do |line| if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures - key = convert_to_backward_compatible_key(key) - depth = indent.scan(/ /).length + convert_to_backward_compatible_key!(key) + depth = indent.size / 2 if quote.empty? && val.empty? new_hash = {} stack[depth][key] = new_hash @@ -76,14 +76,13 @@ module Bundler end # for settings' keys - def convert_to_backward_compatible_key(key) - key = "#{key}/" if key =~ /https?:/i && key !~ %r{/\Z} - key = key.gsub(".", "__") if key.include?(".") - key + def convert_to_backward_compatible_key!(key) + key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key) + key.gsub!(".", "__") end class << self - private :dump_hash, :convert_to_backward_compatible_key + private :dump_hash, :convert_to_backward_compatible_key! end end end diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb index a447709c74..5847628514 100644 --- a/lib/rubygems/yaml_serializer.rb +++ b/lib/rubygems/yaml_serializer.rb @@ -54,8 +54,8 @@ module Gem str.split(/\r?\n/).each do |line| if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures - key = convert_to_backward_compatible_key(key) - depth = indent.scan(/ /).length + convert_to_backward_compatible_key!(key) + depth = indent.size / 2 if quote.empty? && val.empty? new_hash = {} stack[depth][key] = new_hash @@ -76,14 +76,13 @@ module Gem end # for settings' keys - def convert_to_backward_compatible_key(key) - key = "#{key}/" if key =~ /https?:/i && key !~ %r{/\Z} - key = key.gsub(".", "__") if key.include?(".") - key + def convert_to_backward_compatible_key!(key) + key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key) + key.gsub!(".", "__") end class << self - private :dump_hash, :convert_to_backward_compatible_key + private :dump_hash, :convert_to_backward_compatible_key! end end end |