Avoid the block or return pattern to save Proc allocations#29
Merged
knu merged 1 commit intoruby:masterfrom Jan 11, 2023
Merged
Avoid the block or return pattern to save Proc allocations#29knu merged 1 commit intoruby:masterfrom
block or return pattern to save Proc allocations#29knu merged 1 commit intoruby:masterfrom
Conversation
Using the block param in a boolean context like this cause it to be allocated. Using it with an `if` or `unless` was optimized in 3.2 (ruby/ruby#6286) but using it with `or` or `and` wasn't. ```ruby def foo(&block) block or return 1 end puts RubyVM::InstructionSequence.of(method(:foo)).disasm == disasm: #<ISeq:foo@(irb):11 (11,0)-(13,3)> (catch: false) local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1]) [ 1] block@0<Block> 0000 getblockparam block@0, 0 ( 12)[LiCa] 0003 dup 0004 branchif 10 0006 pop 0007 putobject_INT2FIX_1_ 0008 leave [Re] 0009 putnil 0010 leave ``` versus ``` def foo(&block) return 1 if block end puts RubyVM::InstructionSequence.of(method(:foo)).disasm == disasm: #<ISeq:foo@(irb):15 (15,0)-(17,3)> (catch: false) local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1]) [ 1] block@0<Block> 0000 getblockparamproxy block@0, 0 ( 16)[LiCa] 0003 branchunless 7 0005 putobject_INT2FIX_1_ 0006 leave ( 17)[Re] 0007 putnil ( 16) 0008 leave ```
knu
approved these changes
Jan 11, 2023
Member
|
(I'm late to reply 😅) There's on harm in this and it will be faster on older rubies but in Ruby 3.2 we do actually avoid the block allocation as long as it can't be returned. We use None of that's to say we shouldn't have this change. I think it's more readable (and faster on 3.1 as demonstrated). |
Member
|
👍 good catch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Using the block param in a boolean context like this cause it to be allocated.
Using it with an
iforunlesswas optimized in 3.2 (ruby/ruby#6286) but using it withororandwasn't.versus
That
block_given? orpattern was used in most other methods, but not these 3 for some reason.This patch has a fairly big impact on our app:
FYI @jhawthorn
cc @knu @hsbt @marcandre