Project

General

Profile

Actions

Misc #10983

closed

Why blocks make Ruby methods 439% slower ?

Misc #10983: Why blocks make Ruby methods 439% slower ?

Added by Sega100500 (Сергей Е) over 11 years ago. Updated 3 days ago.

Status:
Closed
Assignee:
-
[ruby-core:<unknown>]

Description

https://www.omniref.com/ruby/2.2.0/symbols/Proc/yield#annotation=4087638&line=711&hn=1

require 'benchmark/ips'

def block_call(&block)
  block.call
end

def just_yield
  yield
end

Benchmark.ips do |x|
  x.report("call") do
    block_call { 1 + 1 }
  end

  x.report("just yield") do
    just_yield { 1 + 1 }
  end

  x.compare!
end

I run on Ruby 2.2.1

Calculating -------------------------------------
                call    40.754k i/100ms
          just yield    69.031k i/100ms
-------------------------------------------------
                call    814.929k (± 4.0%) i/s -      4.075M
          just yield      2.871M (±25.1%) i/s -     12.909M

Comparison:
          just yield:  2871127.3 i/s
                call:   814929.3 i/s - 3.52x slower

Updated by ko1 (Koichi Sasada) over 11 years ago Actions #1

To capture local variables and so on (== an environment) for several frames is too heavy.

For example,

1.times{
  1.times{
    1.times{
      Proc.new{}
    }
  }
}

you need to capture all blocks' environments.
You don't need to capture environments only passing block.
So you need to say "passing block is faster" :)

BTW, I agree it is slow.
Improve the performance on this behavior will be great job.

Updated by nobu (Nobuyoshi Nakada) almost 11 years ago Actions #2 [ruby-core:71428]

  • Description updated (diff)

Updated by Earlopain (Earlopain _) 3 days ago Actions #3 [ruby-core:126405]

  • Status changed from Open to Closed

Today the difference is only ~1.25x slower, not nearly as bad as it used to be.
YJIT also improves both versions by at least 2x, altough it is able to optimize yield more than the explicit call.

Actions

Also available in: PDF Atom