[rubygems/rubygems] Optimize allocations in Gem::Version
From running in a random rails app I have locally, here are the changes 1) for `bundle lock --update --bundler` (forcing Bundler to go through dependency resolution) ``` ==> memprof.after.txt <== Total allocated: 2.98 MB (48307 objects) Total retained: 1.21 MB (16507 objects) ==> memprof.before.txt <== Total allocated: 12.62 MB (198506 objects) Total retained: 1.30 MB (23133 objects) ``` 2) for `bin/rails runner true` (essentially only bundler/setup) ``` ==> memprof.after.txt <== Total allocated: 59.50 kB (1017 objects) Total retained: 25.08 kB (362 objects) ==> memprof.before.txt <== Total allocated: 561.82 kB (8575 objects) Total retained: 27.28 kB (513 objects) ``` https://github.com/rubygems/rubygems/commit/35c8ed2cb8
This commit is contained in:
parent
5810304c2e
commit
bf71b0eda5
@ -311,8 +311,8 @@ module Gem::QueryUtils
|
||||
label = "Installed at"
|
||||
specs.each do |s|
|
||||
version = s.version.to_s
|
||||
version << ", default" if s.default_gem?
|
||||
entry << "\n" << " #{label} (#{version}): #{s.base_dir}"
|
||||
default = ", default" if s.default_gem?
|
||||
entry << "\n" << " #{label} (#{version}#{default}): #{s.base_dir}"
|
||||
label = " " * label.length
|
||||
end
|
||||
end
|
||||
|
@ -162,7 +162,7 @@ class Gem::Version
|
||||
# A string representation of this Version.
|
||||
|
||||
def version
|
||||
@version.dup
|
||||
@version
|
||||
end
|
||||
|
||||
alias_method :to_s, :version
|
||||
@ -173,7 +173,7 @@ class Gem::Version
|
||||
def self.correct?(version)
|
||||
nil_versions_are_discouraged! if version.nil?
|
||||
|
||||
!!(version.to_s =~ ANCHORED_VERSION_PATTERN)
|
||||
ANCHORED_VERSION_PATTERN.match?(version.to_s)
|
||||
end
|
||||
|
||||
##
|
||||
@ -224,9 +224,17 @@ class Gem::Version
|
||||
end
|
||||
|
||||
# If version is an empty string convert it to 0
|
||||
version = 0 if version.is_a?(String) && version =~ /\A\s*\Z/
|
||||
version = 0 if version.is_a?(String) && /\A\s*\Z/.match?(version)
|
||||
|
||||
@version = version.to_s.strip.gsub("-",".pre.")
|
||||
@version = version.to_s
|
||||
|
||||
# optimization to avoid allocation when given an integer, since we know
|
||||
# it's to_s won't have any spaces or dashes
|
||||
unless version.is_a?(Integer)
|
||||
@version = @version.strip
|
||||
@version.gsub!("-",".pre.")
|
||||
end
|
||||
@version = -@version
|
||||
@segments = nil
|
||||
end
|
||||
|
||||
@ -252,7 +260,7 @@ class Gem::Version
|
||||
# same precision. Version "1.0" is not the same as version "1".
|
||||
|
||||
def eql?(other)
|
||||
self.class === other && @version == other._version
|
||||
self.class === other && @version == other.version
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
@ -284,7 +292,7 @@ class Gem::Version
|
||||
end
|
||||
|
||||
def yaml_initialize(tag, map) # :nodoc:
|
||||
@version = map["version"]
|
||||
@version = -map["version"]
|
||||
@segments = nil
|
||||
@hash = nil
|
||||
end
|
||||
@ -302,7 +310,7 @@ class Gem::Version
|
||||
|
||||
def prerelease?
|
||||
unless instance_variable_defined? :@prerelease
|
||||
@prerelease = !(@version =~ /[a-zA-Z]/).nil?
|
||||
@prerelease = /[a-zA-Z]/.match?(version)
|
||||
end
|
||||
@prerelease
|
||||
end
|
||||
@ -354,7 +362,7 @@ class Gem::Version
|
||||
return self <=> self.class.new(other) if (String === other) && self.class.correct?(other)
|
||||
|
||||
return unless Gem::Version === other
|
||||
return 0 if @version == other._version || canonical_segments == other.canonical_segments
|
||||
return 0 if @version == other.version || canonical_segments == other.canonical_segments
|
||||
|
||||
lhsegments = canonical_segments
|
||||
rhsegments = other.canonical_segments
|
||||
@ -381,10 +389,26 @@ class Gem::Version
|
||||
end
|
||||
|
||||
def canonical_segments
|
||||
@canonical_segments ||=
|
||||
_split_segments.map! do |segments|
|
||||
segments.reverse_each.drop_while {|s| s == 0 }.reverse
|
||||
end.reduce(&:concat)
|
||||
@canonical_segments ||= begin
|
||||
numeric_segments, string_segments = _split_segments
|
||||
canonical_segments = []
|
||||
|
||||
seen_non_zero = false
|
||||
string_segments.reverse_each do |segment|
|
||||
if seen_non_zero || (seen_non_zero = (segment != 0))
|
||||
canonical_segments << segment
|
||||
end
|
||||
end
|
||||
seen_non_zero = false
|
||||
numeric_segments.reverse_each do |segment|
|
||||
if seen_non_zero || (seen_non_zero = (segment != 0))
|
||||
canonical_segments << segment
|
||||
end
|
||||
end
|
||||
|
||||
canonical_segments.reverse!
|
||||
canonical_segments.freeze
|
||||
end
|
||||
end
|
||||
|
||||
def freeze
|
||||
@ -395,17 +419,13 @@ class Gem::Version
|
||||
|
||||
protected
|
||||
|
||||
def _version
|
||||
@version
|
||||
end
|
||||
|
||||
def _segments
|
||||
# segments is lazy so it can pick up version values that come from
|
||||
# old marshaled versions, which don't go through marshal_load.
|
||||
# since this version object is cached in @@all, its @segments should be frozen
|
||||
|
||||
@segments ||= @version.scan(/[0-9]+|[a-z]+/i).map do |s|
|
||||
/^\d+$/.match?(s) ? s.to_i : s
|
||||
@segments ||= @version.scan(/[0-9]+|[a-z]+/i).map! do |s|
|
||||
/^\d+$/.match?(s) ? s.to_i : -s
|
||||
end.freeze
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user