-
Notifications
You must be signed in to change notification settings - Fork 35
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
Optimize initializer #56
Optimize initializer #56
Conversation
1690460
to
5b60000
Compare
Codecov Report
@@ Coverage Diff @@
## master #56 +/- ##
==========================================
- Coverage 98.79% 96.42% -2.37%
==========================================
Files 1 1
Lines 83 84 +1
==========================================
- Hits 82 81 -1
- Misses 1 3 +2
Continue to review full report at Codecov.
|
👍 from me. @tcrayford can you take a look please? |
"@#{fields[idx]} = values[#{idx}]" | ||
end.join("\n") | ||
|
||
class_eval <<-RUBY |
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 looks great, thanks! Mind adding a comment here mentioning this optimization? Whilst this library doesn't change much, I like to prevent opportunities for bitrot where possible.
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 for the review -- I added a comment above this section to explain a bit more of what's happening and to point back to the PR. Does that cover what you were hoping for?
This PR is inspired by tcrayford#56, and assumes that code will be merged, so uses it in the benchmarks here: https://gist.github.com/ms-ati/fa8002ef8a0ce00716e9aa6510d3d4d9 It is common in our code, as in any idiomatic code using value objects in loops or pipelines, to call `#with` many times, returning a new immutable object each time with 1 or more fields replaced with new values. The optimizations in this PR eliminate a number of extra Hash and Array instantiations that were occurring each time, in favor of iterating only over the constant `VALUE_ATTRS` array and doing key lookups in the given Hash parameter in the hot paths. Per the gist above, this increases ips (iterations per second) 2.29x, from 335.9 to 769.6 on my machine.
nice, thanks! I'll cut a new release over the weekend if I get time. |
This PR is inspired by tcrayford#56, and assumes that code will be merged, so uses it in the benchmarks here: https://gist.github.com/ms-ati/fa8002ef8a0ce00716e9aa6510d3d4d9 It is common in our code, as in any idiomatic code using value objects in loops or pipelines, to call `#with` many times, returning a new immutable object each time with 1 or more fields replaced with new values. The optimizations in this PR eliminate a number of extra Hash and Array instantiations that were occurring each time, in favor of iterating only over the constant `VALUE_ATTRS` array and doing key lookups in the given Hash parameter in the hot paths. Per the gist above, this increases ips (iterations per second) 2.29x, from 335.9 to 769.6 on my machine.
This PR is inspired by tcrayford#56, and assumes that code will be merged, so uses it in the benchmarks here: https://gist.github.com/ms-ati/fa8002ef8a0ce00716e9aa6510d3d4d9 It is common in our code, as in any idiomatic code using value objects in loops or pipelines, to call `#with` many times, returning a new immutable object each time with 1 or more fields replaced with new values. The optimizations in this PR eliminate a number of extra Hash and Array instantiations that were occurring each time, in favor of iterating only over the constant `VALUE_ATTRS` array and doing key lookups in the given Hash parameter in the hot paths. Per the gist above, this increases ips (iterations per second) 2.29x, from 335.9 to 769.6 on my machine.
We use the Values gem extensively in our application and in some pipelines allocate hundreds of thousands of these objects. As a result we're particularly sensitive to the performance of the
#initialize
method.By switching from
define_method
to aclass_eval
, we roughly 2x the number of allocations that can be performed in a given timespan:value is the original implementaion and value2 is the code provided in this patch. See https://gist.github.com/michaeldiscala/cee9dbefa06e0d73e15d5bb095ba11bd for the benchmark script.