Skip to content

Commit

Permalink
Avoid constructing a Regexp when splitting a String with negative limit
Browse files Browse the repository at this point in the history
When splitting a string using a String pattern, we don't want to turn it
into a Regexp unless we absolutely have to. Prior to this change,
passing a negative limit into String#split would have forced this
conversion and incurred a high performance cost as a result.

Running the benchmark for this particular case shows a three-fold
improvement.
  • Loading branch information
leocassarani committed Apr 17, 2013
1 parent 7978c7d commit 04ca45e
Showing 1 changed file with 19 additions and 12 deletions.
31 changes: 19 additions & 12 deletions kernel/common/splitter.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -39,19 +39,24 @@ def self.split(string, pattern, limit)
else else
pattern = StringValue(pattern) unless pattern.kind_of?(String) pattern = StringValue(pattern) unless pattern.kind_of?(String)


if !limited and limit.equal?(undefined) trim_end = !tail_empty || limit == 0

unless limited
if pattern.empty? if pattern.empty?
ret = [] if trim_end
pos = 0 ret = []
pos = 0
str_size = string.num_bytes


while pos < string.num_bytes while pos < str_size
ret << string.byteslice(pos, 1) ret << string.byteslice(pos, 1)
pos += 1 pos += 1
end end


return ret return ret
end
else else
return split_on_string(string, pattern) return split_on_string(string, pattern, trim_end)
end end
end end


Expand Down Expand Up @@ -111,7 +116,7 @@ def self.split(string, pattern, limit)
ret ret
end end


def self.split_on_string(string, pattern) def self.split_on_string(string, pattern, trim_end)
pos = 0 pos = 0


ret = [] ret = []
Expand All @@ -132,8 +137,10 @@ def self.split_on_string(string, pattern)
# No more separators, but we need to grab the last part still. # No more separators, but we need to grab the last part still.
ret << string.byteslice(pos, str_size - pos) ret << string.byteslice(pos, str_size - pos)


while s = ret.at(-1) and s.empty? if trim_end
ret.pop while s = ret.at(-1) and s.empty?
ret.pop
end
end end


ret ret
Expand Down

0 comments on commit 04ca45e

Please sign in to comment.