Optimize checking for interrupts by replacing any? with NOT empty?#380
Conversation
|
@Shopify/liquid ping |
|
Thanks @camilo -- didn't know there was a group. |
|
🚀 ✨ |
|
⛵ awesome ✨ |
|
lolwutruby |
|
I think 8.7% improvement deserves a regression test |
|
@fw42 https://github.com/ruby/ruby/blob/bb51e69af06268b26af96698a8903f06c284c1f6/enum.c#L1087-L1092 It's the |
Does it make sense to push that change as well? Seems useful. |
|
maybe have both profiles yes, but it'd be a seperate PR IMO, @jasonhl maybe update CHANGELOG |
This is not easy to test I think, how'd you go about it ( besides expecting that .any? did not get call) |
|
@camilo: Yeah dunno, maybe just as simple as test "use empty? instead of any? because it's way faster, dont fucking change this!" do
...
something.expects(:any?).never
something.expects(:empty?)
endNot pretty, but I think this improvement would be worth the ugly test. In two weeks, someone is gonna be all "oh, I don't like negations, let's just use |
|
For more reference: Shopify/ruby#4 |
|
Nice to know that my semantic improvement only cost 8.7% in performance. You learn something every day :) |
|
lol @d-Pixie If it makes you feel any better, it gave me the opportunity to change liquid for the first time :-) |
|
@fw42: Test added. Had to do the cleanup of spy explicitly in the teardown to get it to work, but it's not so bad. |
|
@camilo: CHANGELOG? Did you mean this file: https://github.com/Shopify/liquid/blob/master/History.md or...? |
|
@jasonhl yes that one so it goes as a thing in the next release |
|
❤️ |
@csfrancis you mind submitting a patch upstream that memoizes |
There was a problem hiding this comment.
❤️ the use of spy to avoid affecting the behaviour of the code
There was a problem hiding this comment.
channeling your wisdom here @dylanahsmith
|
Yeah @dylanahsmith - I'm planning on submitting Shopify/ruby#5 upstream once Charlie 👍's. |
|
👍 |
|
also |
Optimize checking for interrupts by replacing any? with NOT empty?
Doing an object allocation profile on Shopify in production using stackprof reveals that the number three generator of objects is Liquid#context has_interrupt?
The method is called in the main flow of the block rendering, which means it is called a lot. The documentation for .any? (http://ruby-doc.org/core-2.1.2/Enumerable.html#method-i-any-3F) states that:
Note the 'implicit block' bit -- that's where the allocation comes from.
Changed this to !empty, which is equivalent if (and only if) the array in question cannot contain nil/false values. The
@interruptsmember is only altered by push_interrupt, which is only ever called with a the keywords break or continue, so this is perfectly safe.The existing tests appear to cover both the break and continue tags, so I did not add any as this should not alter behaviour in any way.
I temporarily altered the the code in profile.rb to benchmark object allocation.
Here's before:
Here's with the change in this PR:
833,800 (8.7%) less objects allocated :-)
@camilo, @boourns, @dylanahsmith: Code review, please.
CC: @csfrancis