Skip to content

Conversation

@kenhys
Copy link
Contributor

@kenhys kenhys commented Apr 27, 2025

Which issue(s) this PR fixes:
Fixes #

What this PR does / why we need it:

This is cosmetic change, it does not change behavior at all. The following rubocop configuration detects it.

Performance/RedundantBlockCall:
  Enable: true

Benchmark result:

ruby 3.2.8 (2025-03-26 revision 13f495dc2c) +YJIT [x86_64-linux]
Warming up --------------------------------------
          block call     1.296M i/100ms
   yield with &block     1.708M i/100ms
yield without &block     1.687M i/100ms
Calculating -------------------------------------
          block call     12.964M (± 0.8%) i/s   (77.14 ns/i) -     66.097M in   5.098814s
   yield with &block     17.186M (± 0.5%) i/s   (58.19 ns/i) -     87.092M in   5.067659s
yield without &block     17.162M (± 0.3%) i/s   (58.27 ns/i) -     86.062M in   5.014579s

Comparison:
   yield with &block: 17186340.4 i/s
yield without &block: 17162477.2 i/s - same-ish: difference falls within error
          block call: 12964086.6 i/s - 1.33x  slower

yield with/without &block is same-ish. For simplicity, use without &block.

Appendix: benchmark script

require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'benchmark-ips'
  gem 'benchmark-memory'
end

def block_call(s, &block)
  block.call(s) if block_given?
end

def yield_with_block(s, &block)
  yield(s) if block_given?
end

def yield_without_block(s)
  yield(s) if block_given?
end

Benchmark.ips do |x|
  x.report("block call") {
    block_call("dummy") do |message|
      message
    end
  }
  x.report("yield with &block") {
    yield_with_block("dummy") do |message|
      message
    end
  }
  x.report("yield without &block") {
    yield_without_block("dummy") do |message|
      message
    end
  }
  x.compare!
end

Docs Changes:

N/A

Release Note:

N/A

This is cosmetic change, it does not change behavior at all. The following rubocop configuration detects it.

```
Performance/RedundantBlockCall:
  Enable: true
```

Benchmark result:

```
ruby 3.2.8 (2025-03-26 revision 13f495dc2c) +YJIT [x86_64-linux]
Warming up --------------------------------------
          block call     1.296M i/100ms
   yield with &block     1.708M i/100ms
yield without &block     1.687M i/100ms
Calculating -------------------------------------
          block call     12.964M (± 0.8%) i/s   (77.14 ns/i) -     66.097M in   5.098814s
   yield with &block     17.186M (± 0.5%) i/s   (58.19 ns/i) -     87.092M in   5.067659s
yield without &block     17.162M (± 0.3%) i/s   (58.27 ns/i) -     86.062M in   5.014579s

Comparison:
   yield with &block: 17186340.4 i/s
yield without &block: 17162477.2 i/s - same-ish: difference falls within error
          block call: 12964086.6 i/s - 1.33x  slower
```

yield with/without &block is same-ish. For simplicity, use without &block.

Appendix: benchmark script

```ruby
require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'benchmark-ips'
  gem 'benchmark-memory'
end

def block_call(s, &block)
  block.call(s) if block_given?
end

def yield_with_block(s, &block)
  yield(s) if block_given?
end

def yield_without_block(s)
  yield(s) if block_given?
end

Benchmark.ips do |x|
  x.report("block call") {
    block_call("dummy") do |message|
      message
    end
  }
  x.report("yield with &block") {
    yield_with_block("dummy") do |message|
      message
    end
  }
  x.report("yield without &block") {
    yield_without_block("dummy") do |message|
      message
    end
  }
  x.compare!
end
```

Signed-off-by: Kentaro Hayashi <[email protected]>
@kenhys kenhys closed this Apr 28, 2025
@kenhys kenhys deleted the rubocop-redundant-block-call branch May 27, 2025 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant