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
Avoid extra allocation in String#from and #to #36180
Avoid extra allocation in String#from and #to #36180
Conversation
Can you improve |
Removes unnecessary Range object allocations for a significant speed-up. String#from Comparison: new: 3378594.0 i/s old: 2380129.8 i/s - 1.42x slower String#to Comparison: new: 2866175.7 i/s old: 2304406.4 i/s - 1.24x slower
5906547
to
52498cc
Compare
@kamipo Done! |
@@ -61,7 +61,8 @@ def from(position) | |||
# str.from(0).to(-1) # => "hello" | |||
# str.from(1).to(-2) # => "ell" | |||
def to(position) | |||
self[0..position] | |||
position = [position + length, -1].max if position < 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.
Curious what the -1 and max
here is for? I could get all tests to pass with: position += size if position < 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 suppose the condition does not preserve the original behavior, or hard to understand what this do.
Maybe we should more exercise that in 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.
It is for when position + length
is less than -1
.
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.
@rafaelfranca Yes, exactly.
For example, "foo".to(-10)
without the max
becomes "foo"[0, -10 + 3 + 1]
or "foo"[0, -6]
, which returns nil
.
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, I see! I found relying on -1 + 1 to get a 0 length for String#[] a little confusing, so I tried to change it a bit in efa2299 with extra 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.
@kaspth I had considered that variation, because it is a bit more clear. But, I decided to use max
because the extra to_s
makes it ~13% slower when the position isn't negative. Of course, it's only a micro-benchmark and likely of no consequence, but since the purpose of the PR was performance, that's what I went 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.
Changed to fastest variant 71e41a5.
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.
@kamipo Excellent! 👍
These performance optimizations have been contributed to Active Support in rails/rails#36180.
Removes unnecessary Range object allocations for a significant speed-up.