Rubyの似たメソッドのベンチマーク結果比較 まとめ

  • 30
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

JuanitoFatas/fast-rubyにRubyの役割の似たメソッドのパフォーマンスがまとまっていたが、結果だけでなくコードも並べて一覧化したかったので、当該リポジトリをcloneしてきて、以下のscriptを実行してまとめなおした。

File.open('./result.md', 'w') do |dest|
  $stdout = dest
  Dir.glob('code/**/*rb').each do |f|
    dest.puts "## #{File.basename(f, '.rb')}"
    dest.puts "\`\`\`rb"
    dest.puts File.open(f).read
    dest.puts "\`\`\`"
    dest.puts
    dest.puts "\`\`\`"
    require "./#{f}"
    dest.puts "\`\`\`"
    dest.puts
    dest.flush
  end
  $stdout = STDOUT
end


ベンチマーク結果

array-first-vs-index

require 'benchmark/ips'

ARRAY = [*1..100]

def fast
  ARRAY[0]
end

def slow
  ARRAY.first
end

Benchmark.ips do |x|
  x.report('Array#[0]') { fast }
  x.report('Array#first') { slow }
  x.compare!
end
Calculating -------------------------------------
           Array#[0]   131.571k i/100ms
         Array#first   113.343k i/100ms
-------------------------------------------------
           Array#[0]      6.857M (±12.6%) i/s -     33.682M
         Array#first      6.162M (±13.1%) i/s -     30.263M

Comparison:
           Array#[0]:  6856904.5 i/s
         Array#first:  6161728.1 i/s - 1.11x slower

array-last-vs-index

require 'benchmark/ips'

ARRAY = [*1..100]

def fast
  ARRAY[-1]
end

def slow
  ARRAY.last
end

Benchmark.ips do |x|
  x.report('Array#[-1]') { fast }
  x.report('Array#last') { slow }
  x.compare!
end
Calculating -------------------------------------
          Array#[-1]   111.222k i/100ms
          Array#last   116.127k i/100ms
-------------------------------------------------
          Array#[-1]      6.130M (±23.9%) i/s -     24.803M
          Array#last      5.852M (±17.0%) i/s -     27.987M

Comparison:
          Array#[-1]:  6130128.5 i/s
          Array#last:  5851541.4 i/s - 1.05x slower

bsearch-vs-find

require 'benchmark/ips'

data = [*0..100_000_000]

Benchmark.ips do |x|
  x.report('find')    { data.find    { |number| number > 77_777_777 } }
  x.report('bsearch') { data.bsearch { |number| number > 77_777_777 } }
  x.compare!
end
Calculating -------------------------------------
                find     1.000  i/100ms
             bsearch    37.434k i/100ms
-------------------------------------------------
                find      0.165  (± 0.0%) i/s -      1.000  in   6.070512s
             bsearch    506.841k (±10.8%) i/s -      2.508M

Comparison:
             bsearch:   506840.8 i/s
                find:        0.2 i/s - 3076783.30x slower

length-vs-size-vs-count

require 'benchmark/ips'

ARRAY = [*1..100]

Benchmark.ips do |x|
  x.report("Array#length") { ARRAY.length }
  x.report("Array#size") { ARRAY.size }
  x.report("Array#count") { ARRAY.count }
  x.compare!
end
Calculating -------------------------------------
        Array#length   123.940k i/100ms
          Array#size   130.562k i/100ms
         Array#count   121.857k i/100ms
-------------------------------------------------
        Array#length      8.985M (±12.4%) i/s -     44.123M
          Array#size      9.032M (±13.6%) i/s -     44.261M
         Array#count      7.513M (±13.2%) i/s -     36.801M

Comparison:
          Array#size:  9031746.3 i/s
        Array#length:  8984738.0 i/s - 1.01x slower
         Array#count:  7513273.8 i/s - 1.20x slower

shuffle-first-vs-sample

require 'benchmark/ips'

ARRAY = [*1..100]

def slow
  ARRAY.shuffle.first
end

def fast
  ARRAY.sample
end

Benchmark.ips do |x|
  x.report('Array#shuffle.first') { slow }
  x.report('Array#sample')        { fast }
  x.compare!
end
Calculating -------------------------------------
 Array#shuffle.first    26.626k i/100ms
        Array#sample   124.589k i/100ms
-------------------------------------------------
 Array#shuffle.first    338.634k (± 5.8%) i/s -      1.704M
        Array#sample      5.614M (± 8.3%) i/s -     27.908M

Comparison:
        Array#sample:  5614280.3 i/s
 Array#shuffle.first:   338633.5 i/s - 16.58x slower

each-push-vs-map

require 'benchmark/ips'

ARRAY = (1..100).to_a

def slow
  array = []
  ARRAY.each { |i| array.push i }
end

def fast
  ARRAY.map { |i| i }
end

Benchmark.ips do |x|
  x.report('Array#each + push') { slow }
  x.report('Array#map')         { fast }
  x.compare!
end
Calculating -------------------------------------
   Array#each + push     8.973k i/100ms
           Array#map    14.217k i/100ms
-------------------------------------------------
   Array#each + push    100.595k (± 4.8%) i/s -    502.488k
           Array#map    149.678k (± 8.9%) i/s -    753.501k

Comparison:
           Array#map:   149678.3 i/s
   Array#each + push:   100594.6 i/s - 1.49x slower

each-vs-for-loop

require 'benchmark/ips'

ARRAY = [*1..100]

def slow
  for number in ARRAY do
    number
  end
end

def fast
  ARRAY.each do |number|
    number
  end
end

Benchmark.ips do |x|
  x.report('For loop') { slow  }
  x.report('#each')    { fast  }
  x.compare!
end
Calculating -------------------------------------
            For loop    15.967k i/100ms
               #each    16.048k i/100ms
-------------------------------------------------
            For loop    187.693k (± 8.2%) i/s -    942.053k
               #each    202.448k (± 7.6%) i/s -      1.011M

Comparison:
               #each:   202448.2 i/s
            For loop:   187693.1 i/s - 1.08x slower

each_with_index-vs-while-loop

require 'benchmark/ips'

ARRAY = [*1..100]

def slow
  ARRAY.each_with_index do |number, index|
    number + index
  end
end

def fast
  index = 0
  while index < ARRAY.size
    ARRAY[index] + index
    index += 1
  end
end

Benchmark.ips do |x|
  x.report('each_with_index') { slow  }
  x.report('While Loop')      { fast  }
  x.compare!
end
Calculating -------------------------------------
     each_with_index    10.956k i/100ms
          While Loop    20.837k i/100ms
-------------------------------------------------
     each_with_index    125.882k (± 8.3%) i/s -    635.448k
          While Loop    227.617k (±10.6%) i/s -      1.125M

Comparison:
          While Loop:   227616.9 i/s
     each_with_index:   125881.7 i/s - 1.81x slower

map-flatten-vs-flat_map

require 'benchmark/ips'

ARRAY = (1..100).to_a

def slow_flatten_1
  ARRAY.map { |e| [e, e] }.flatten(1)
end

def slow_flatten
  ARRAY.map { |e| [e, e] }.flatten
end

def fast
  ARRAY.flat_map { |e| [e, e] }
end

Benchmark.ips do |x|
  x.report('Array#map.flatten(1)') { slow_flatten_1 }
  x.report('Array#map.flatten')    { slow_flatten   }
  x.report('Array#flat_map')       { fast           }
  x.compare!
end
Calculating -------------------------------------
Array#map.flatten(1)     3.154k i/100ms
   Array#map.flatten     3.284k i/100ms
      Array#flat_map     5.309k i/100ms
-------------------------------------------------
Array#map.flatten(1)     32.836k (± 7.9%) i/s -    164.008k
   Array#map.flatten     29.514k (±24.6%) i/s -    118.224k
      Array#flat_map     53.059k (± 7.6%) i/s -    265.450k

Comparison:
      Array#flat_map:    53058.9 i/s
Array#map.flatten(1):    32835.9 i/s - 1.62x slower
   Array#map.flatten:    29514.3 i/s - 1.80x slower

reverse-each-vs-reverse_each

require 'benchmark/ips'

ARRAY = (1..100).to_a

def slow
  ARRAY.reverse.each{|x| x}
end

def fast
  ARRAY.reverse_each{|x| x}
end

Benchmark.ips do |x|
  x.report('Array#reverse.each') { slow }
  x.report('Array#reverse_each') { fast }
  x.compare!
end
Calculating -------------------------------------
  Array#reverse.each    16.169k i/100ms
  Array#reverse_each    17.777k i/100ms
-------------------------------------------------
  Array#reverse.each    179.836k (± 6.1%) i/s -    905.464k
  Array#reverse_each    195.553k (± 5.1%) i/s -    977.735k

Comparison:
  Array#reverse_each:   195553.5 i/s
  Array#reverse.each:   179836.0 i/s - 1.09x slower

select-first-vs-detect

require 'benchmark/ips'

ARRAY = [*1..100]

def slow
  ARRAY.select { |x| x.eql?(15) }.first
end

def fast
  ARRAY.detect { |x| x.eql?(15) }
end

Benchmark.ips(20) do |x|
  x.report('Enumerable#select.first') { slow }
  x.report('Enumerable#detect') { fast }
  x.compare!
end
Calculating -------------------------------------
Enumerable#select.first
                         7.842k i/100ms
   Enumerable#detect    30.959k i/100ms
-------------------------------------------------
Enumerable#select.first
                         85.007k (± 4.6%) i/s -      1.702M
   Enumerable#detect    377.348k (±11.0%) i/s -      7.461M

Comparison:
   Enumerable#detect:   377348.3 i/s
Enumerable#select.first:    85007.3 i/s - 4.44x slower

select-last-vs-reverse-detect

require 'benchmark/ips'

ARRAY = [*1..100]

def fast
  ARRAY.reverse.detect { |x| (x % 10).zero? }
end

def slow
  ARRAY.select { |x| (x % 10).zero? }.last
end

Benchmark.ips do |x|
  x.report('Enumerable#reverse.detect') { fast }
  x.report('Enumerable#select.last')    { slow }
  x.compare!
end
Calculating -------------------------------------
Enumerable#reverse.detect
                        43.007k i/100ms
Enumerable#select.last
                         8.944k i/100ms
-------------------------------------------------
Enumerable#reverse.detect
                        689.440k (±11.4%) i/s -      3.441M
Enumerable#select.last
                        103.319k (± 9.6%) i/s -    518.752k

Comparison:
Enumerable#reverse.detect:   689440.2 i/s
Enumerable#select.last:   103319.2 i/s - 6.67x slower

sort-vs-sort_by

require 'benchmark/ips'

User  = Struct.new(:name)
ARRAY = Array.new(100) do
  User.new(sprintf "%010d", rand(1_000_000_000))
end

def slow
  ARRAY.sort { |a, b| a.name <=> b.name }
end

def fast
  ARRAY.sort_by(&:name)
end

Benchmark.ips do |x|
  x.report('Enumerable#sort')    { slow }
  x.report('Enumerable#sort_by') { fast }
  x.compare!
end
Calculating -------------------------------------
     Enumerable#sort     1.106k i/100ms
  Enumerable#sort_by     2.344k i/100ms
-------------------------------------------------
     Enumerable#sort     10.868k (± 7.9%) i/s -     54.194k
  Enumerable#sort_by     24.546k (± 4.6%) i/s -    124.232k

Comparison:
  Enumerable#sort_by:    24545.5 i/s
     Enumerable#sort:    10868.3 i/s - 2.26x slower

assignment

require 'benchmark/ips'

def fast
  a, b, c, d, e, f, g, h = 1, 2, 3, 4, 5, 6, 7, 8
  nil
end

def slow
  a = 1
  b = 2
  c = 3
  d = 4
  e = 5
  f = 6
  g = 7
  h = 8
  nil
end

Benchmark.ips do |x|
  x.report('Parallel Assignment')   { fast }
  x.report('Sequential Assignment') { slow }
  x.compare!
end
Calculating -------------------------------------
 Parallel Assignment   124.614k i/100ms
Sequential Assignment
                       121.407k i/100ms
-------------------------------------------------
 Parallel Assignment      5.282M (± 6.7%) i/s -     26.294M
Sequential Assignment
                          5.259M (± 9.9%) i/s -     26.103M

Comparison:
 Parallel Assignment:  5282329.4 i/s
Sequential Assignment:  5259354.5 i/s - 1.00x slower

attr-accessor-vs-getter-and-setter

require 'benchmark/ips'

class User
  attr_accessor :first_name

  def last_name
    @last_name
  end

  def last_name=(value)
    @last_name = value
  end

end

def slow
  user = User.new
  user.last_name = 'John'
  user.last_name
end

def fast
  user = User.new
  user.first_name = 'John'
  user.first_name
end

Benchmark.ips do |x|
  x.report('getter_and_setter') { slow }
  x.report('attr_accessor')     { fast }
  x.compare!
end
Calculating -------------------------------------
   getter_and_setter    45.927k i/100ms
       attr_accessor    38.350k i/100ms
-------------------------------------------------
   getter_and_setter    594.639k (±18.3%) i/s -      2.847M
       attr_accessor    685.580k (±11.8%) i/s -      3.375M

Comparison:
       attr_accessor:   685580.1 i/s
   getter_and_setter:   594638.6 i/s - 1.15x slower

begin-rescue-vs-respond-to

require 'benchmark/ips'

def slow
  begin
    writing
  rescue
    'fast ruby'
  end
end

def fast
  if respond_to?(:writing)
    writing
  else
    'fast ruby'
  end
end

Benchmark.ips do |x|
  x.report('begin...rescue') { slow }
  x.report('respond_to?')    { fast }
  x.compare!
end
Calculating -------------------------------------
      begin...rescue    22.909k i/100ms
         respond_to?    83.178k i/100ms
-------------------------------------------------
      begin...rescue    249.899k (±11.8%) i/s -      1.237M
         respond_to?      2.985M (± 9.1%) i/s -     14.889M

Comparison:
         respond_to?:  2984924.2 i/s
      begin...rescue:   249899.1 i/s - 11.94x slower

block-apply-method

require "benchmark/ips"

def do_something(n)
  4*n + 2
end

def fast
  [1, 2, 3].map { |n| do_something(n) }
end

def slow
  [1, 2, 3].map(&method(:do_something))
end

Benchmark.ips do |x|
  x.report("normal")  { fast }
  x.report("&method") { slow }
  x.compare!
end
Calculating -------------------------------------
              normal    66.189k i/100ms
             &method    29.728k i/100ms
-------------------------------------------------
              normal      1.382M (±12.7%) i/s -      6.817M
             &method    422.184k (± 5.8%) i/s -      2.111M

Comparison:
              normal:  1382093.6 i/s
             &method:   422184.1 i/s - 3.27x slower

define_method-vs-module-eval

require 'benchmark/ips'

def method_names(number)
  number.times.map do
    10.times.inject("") { |e| e << ('a'..'z').to_a.sample}
  end
end

class DefineMethod
  def self.def_methods(_methods)
    _methods.each do |method_name|
      define_method method_name do
        puts "win"
      end
    end
  end
end

class ModuleEvalWithString
  def self.def_methods(_methods)
    _methods.each do |method_name|
      module_eval %{
        def #{method_name}
          puts "win"
        end
      }
    end
  end
end

def fast
  DefineMethod.def_methods(method_names(10))
end

def slow
  ModuleEvalWithString.def_methods(method_names(10))
end


Benchmark.ips do |x|
  x.report("module_eval with string") { slow }
  x.report("define_method")           { fast }
  x.compare!
end
Calculating -------------------------------------
module_eval with string
                       116.000  i/100ms
       define_method   128.000  i/100ms
-------------------------------------------------
module_eval with string
                          1.008k (±25.9%) i/s -      4.756k
       define_method      1.335k (±27.2%) i/s -      6.400k

Comparison:
       define_method:     1335.2 i/s
module_eval with string:     1007.7 i/s - 1.32x slower

bracket-vs-dup

require 'benchmark/ips'

HASH = Hash[*('a'..'z').to_a]

def fast
  Hash[HASH]
end

def slow
  HASH.dup
end

Benchmark.ips do |x|
  x.report("Hash[]")   { fast }
  x.report("Hash#dup") { slow }
  x.compare!
end
Calculating -------------------------------------
              Hash[]    13.880k i/100ms
            Hash#dup     9.536k i/100ms
-------------------------------------------------
              Hash[]    387.204k (±50.8%) i/s -      1.041M
            Hash#dup    157.026k (±26.0%) i/s -    696.128k

Comparison:
              Hash[]:   387204.1 i/s
            Hash#dup:   157025.5 i/s - 2.47x slower

bracket-vs-fetch

require "benchmark/ips"

HASH_WITH_SYMBOL = { fast: "ruby" }
HASH_WITH_STRING = { "fast" => "ruby" }

def fastest
  HASH_WITH_SYMBOL[:fast]
end

def faster
  HASH_WITH_SYMBOL.fetch(:fast)
end

def fast
  HASH_WITH_STRING["fast"]
end

def slow
  HASH_WITH_STRING.fetch("fast")
end

Benchmark.ips do |x|
  x.report("Hash#[], symbol")    { fastest }
  x.report("Hash#fetch, symbol") { faster  }
  x.report("Hash#[], string")    { fast    }
  x.report("Hash#fetch, string") { slow    }
  x.compare!
end
Calculating -------------------------------------
     Hash#[], symbol    98.214k i/100ms
  Hash#fetch, symbol   109.606k i/100ms
     Hash#[], string   111.998k i/100ms
  Hash#fetch, string    88.703k i/100ms
-------------------------------------------------
     Hash#[], symbol      6.705M (± 8.2%) i/s -     33.295M
  Hash#fetch, symbol      5.538M (±13.3%) i/s -     27.182M
     Hash#[], string      5.335M (±11.7%) i/s -     26.320M
  Hash#fetch, string      2.600M (±36.4%) i/s -     10.910M

Comparison:
     Hash#[], symbol:  6704658.0 i/s
  Hash#fetch, symbol:  5538280.0 i/s - 1.21x slower
     Hash#[], string:  5335044.6 i/s - 1.26x slower
  Hash#fetch, string:  2599819.2 i/s - 2.58x slower

fetch-vs-fetch-with-block

require "benchmark/ips"

HASH = { writing: :fast_ruby }

def fast
  HASH.fetch(:writing) { "fast ruby" }
end

def slow
  HASH.fetch(:writing, "fast ruby")
end

Benchmark.ips do |x|
  x.report("Hash#fetch + block") { fast }
  x.report("Hash#fetch + arg")   { slow }
  x.compare!
end
Calculating -------------------------------------
  Hash#fetch + block    98.900k i/100ms
    Hash#fetch + arg    82.399k i/100ms
-------------------------------------------------
  Hash#fetch + block      4.791M (±14.5%) i/s -     23.340M
    Hash#fetch + arg      2.944M (±37.7%) i/s -     11.948M

Comparison:
  Hash#fetch + block:  4790810.9 i/s
    Hash#fetch + arg:  2943745.5 i/s - 1.63x slower

hash-key-sort_by-vs-sort

require "benchmark/ips"

HASH = Hash[*("a".."z").to_a.shuffle]

def fast
  HASH.sort_by { |k, _v| k }.to_h
end

def slow
  HASH.sort.to_h
end

Benchmark.ips do |x|
  x.report("sort_by + to_h") { fast }
  x.report("sort + to_h")    { slow }
  x.compare!
end
Calculating -------------------------------------
      sort_by + to_h     7.383k i/100ms
         sort + to_h     4.767k i/100ms
-------------------------------------------------
      sort_by + to_h     86.372k (±23.4%) i/s -    413.448k
         sort + to_h     60.025k (±19.4%) i/s -    290.787k

Comparison:
      sort_by + to_h:    86372.0 i/s
         sort + to_h:    60025.1 i/s - 1.44x slower

keys-each-vs-each_key

require 'benchmark/ips'

HASH = {
  'provider' => 'facebook',
  'uid' => '1234567',
  'info' => {
    'nickname' => 'jbloggs',
    'email' => 'joe@bloggs.com',
    'name' => 'Joe Bloggs',
    'first_name' => 'Joe',
    'last_name' => 'Bloggs',
    'image' => 'http://graph.facebook.com/1234567/picture?type=square',
    'urls' => { 'Facebook' => 'http://www.facebook.com/jbloggs' },
    'location' => 'Palo Alto, California',
    'verified' => true
  },
  'credentials' => {
    'token' => 'ABCDEF...',
    'expires_at' => 1321747205,
    'expires' => true
  },
  'extra' => {
    'raw_info' => {
      'id' => '1234567',
      'name' => 'Joe Bloggs',
      'first_name' => 'Joe',
      'last_name' => 'Bloggs',
      'link' => 'http://www.facebook.com/jbloggs',
      'username' => 'jbloggs',
      'location' => { 'id' => '123456789', 'name' => 'Palo Alto, California' },
      'gender' => 'male',
      'email' => 'joe@bloggs.com',
      'timezone' => -8,
      'locale' => 'en_US',
      'verified' => true,
      'updated_time' => '2011-11-11T06:21:03+0000'
    }
  }
}


def slow
  HASH.keys.each(&:to_sym)
end

def fast
  HASH.each_key(&:to_sym)
end

Benchmark.ips do |x|
  x.report('Hash#keys.each') { slow }
  x.report('Hash#each_key')  { fast }
  x.compare!
end
Calculating -------------------------------------
      Hash#keys.each    47.268k i/100ms
       Hash#each_key    53.456k i/100ms
-------------------------------------------------
      Hash#keys.each    722.908k (±17.4%) i/s -      3.498M
       Hash#each_key    907.306k (±13.6%) i/s -      4.437M

Comparison:
       Hash#each_key:   907306.1 i/s
      Hash#keys.each:   722907.5 i/s - 1.26x slower

merge-bang-vs-[]=

require 'benchmark/ips'

ENUM = (1..100)

def slow
  ENUM.each_with_object({}) do |e, h|
    h.merge!(e => e)
  end
end

def fast
  ENUM.each_with_object({}) do |e, h|
    h[e] = e
  end
end

Benchmark.ips do |x|
  x.report('Hash#merge!') { slow }
  x.report('Hash#[]=') { fast }
  x.compare!
end
Calculating -------------------------------------
         Hash#merge!   667.000  i/100ms
            Hash#[]=     2.407k i/100ms
-------------------------------------------------
         Hash#merge!      8.567k (±25.6%) i/s -     40.020k
            Hash#[]=     30.599k (±32.1%) i/s -    125.164k

Comparison:
            Hash#[]=:    30598.5 i/s
         Hash#merge!:     8566.7 i/s - 3.57x slower

merge-vs-merge-bang

require 'benchmark/ips'

ENUM = (1..100)

def slow
  ENUM.inject({}) do |h, e|
    h.merge(e => e)
  end
end

def fast
  ENUM.inject({}) do |h, e|
    h.merge!(e => e)
  end
end

Benchmark.ips do |x|
  x.report('Hash#merge') { slow }
  x.report('Hash#merge!') { fast }
  x.compare!
end
Calculating -------------------------------------
          Hash#merge    32.000  i/100ms
         Hash#merge!   806.000  i/100ms
-------------------------------------------------
          Hash#merge    423.825  (±35.2%) i/s -      1.664k
         Hash#merge!      8.714k (±29.3%) i/s -     40.300k

Comparison:
         Hash#merge!:     8714.1 i/s
          Hash#merge:      423.8 i/s - 20.56x slower

call-vs-send-vs-method_missing

require "benchmark/ips"

class MethodCall
  def method
  end

  def method_missing(_method,*args)
    method
  end
end

def fastest
  method = MethodCall.new
  method.method
end

def slow
  method = MethodCall.new
  method.send(:method)
end

def slowest
  method = MethodCall.new
  method.not_exist
end

Benchmark.ips do |x|
  x.report("call")           { fastest }
  x.report("send")           { slow    }
  x.report("method_missing") { slowest }
  x.compare!
end
Calculating -------------------------------------
                call    48.463k i/100ms
                send    60.268k i/100ms
      method_missing    66.064k i/100ms
-------------------------------------------------
                call      2.818M (±35.6%) i/s -     10.904M
                send      2.802M (±32.9%) i/s -     11.451M
      method_missing      1.829M (±41.3%) i/s -      7.531M

Comparison:
                call:  2818320.3 i/s
                send:  2802024.1 i/s - 1.01x slower
      method_missing:  1829223.5 i/s - 1.54x slower

block-vs-to_proc

require 'benchmark/ips'

RANGE = (1..100)

def slow
  RANGE.map { |i| i.to_s }
end

def fast
  RANGE.map(&:to_s)
end

Benchmark.ips do |x|
  x.report('Block')          { slow }
  x.report('Symbol#to_proc') { fast }
  x.compare!
end
Calculating -------------------------------------
               Block     2.589k i/100ms
      Symbol#to_proc     2.476k i/100ms
-------------------------------------------------
               Block     26.863k (±21.5%) i/s -    129.450k
      Symbol#to_proc     30.524k (±28.1%) i/s -    146.084k

Comparison:
      Symbol#to_proc:    30523.5 i/s
               Block:    26863.0 i/s - 1.14x slower

proc-call-vs-yield

require 'benchmark/ips'

def slow &block
  block.call
end

def fast
  yield
end

Benchmark.ips do |x|
  x.report('block.call') { slow { 1 + 1 } }
  x.report('yield')      { fast { 1 + 1 } }
  x.compare!
end
Calculating -------------------------------------
          block.call    46.799k i/100ms
               yield    91.226k i/100ms
-------------------------------------------------
          block.call    925.952k (±35.3%) i/s -      4.025M
               yield      5.426M (±11.7%) i/s -     26.638M

Comparison:
               yield:  5425864.6 i/s
          block.call:   925952.4 i/s - 5.86x slower

cover-vs-include

require "benchmark/ips"
require "date"

BEGIN_OF_JULY = Date.new(2015, 7, 1)
END_OF_JULY = Date.new(2015, 7, 31)
DAY_IN_JULY = Date.new(2015, 7, 15)

def fast
  (BEGIN_OF_JULY..END_OF_JULY).cover? DAY_IN_JULY
end

def slow
  (BEGIN_OF_JULY..END_OF_JULY).include? DAY_IN_JULY
end

Benchmark.ips do |x|
  x.report("Range#cover?") { fast }
  x.report("Range#include?") { slow }
  x.compare!
end
Calculating -------------------------------------
        Range#cover?    64.739k i/100ms
      Range#include?     6.715k i/100ms
-------------------------------------------------
        Range#cover?      1.663M (±26.5%) i/s -      7.574M
      Range#include?     66.863k (±20.4%) i/s -    322.320k

Comparison:
        Range#cover?:  1662586.0 i/s
      Range#include?:    66862.8 i/s - 24.87x slower

casecmp-vs-downcase-==

require 'benchmark/ips'

SLUG = 'ABCD'

def slow
  SLUG.downcase == 'abcd'
end

def fast
  SLUG.casecmp('abcd') == 0
end

Benchmark.ips do |x|
  x.report('String#downcase + ==') { slow }
  x.report('String#casecmp')       { fast }
  x.compare!
end
Calculating -------------------------------------
String#downcase + ==    65.024k i/100ms
      String#casecmp    78.475k i/100ms
-------------------------------------------------
String#downcase + ==      2.014M (±44.0%) i/s -      7.933M
      String#casecmp      2.847M (±34.8%) i/s -     11.693M

Comparison:
      String#casecmp:  2847127.5 i/s
String#downcase + ==:  2014318.8 i/s - 1.41x slower

concatenation

require 'benchmark/ips'

# 2 + 1 = 3 object
def slow_plus
  'foo' + 'bar'
end

# 2 + 1 = 3 object
def slow_concat
  'foo'.concat 'bar'
end

# 2 + 1 = 3 object
def slow_append
  'foo' << 'bar'
end

# 1 object
def fast
  'foo' 'bar'
end

Benchmark.ips do |x|
  x.report('String#+')      { slow_plus }
  x.report('String#concat') { slow_concat }
  x.report('String#append') { slow_append }
  x.report('"foo" "bar"')   { fast }
  x.compare!
end
Calculating -------------------------------------
            String#+    64.291k i/100ms
       String#concat    71.554k i/100ms
       String#append    60.970k i/100ms
         "foo" "bar"    84.739k i/100ms
-------------------------------------------------
            String#+      1.582M (±51.4%) i/s -      6.301M
       String#concat      2.078M (±41.7%) i/s -      8.515M
       String#append      2.239M (±44.0%) i/s -      8.719M
         "foo" "bar"      3.941M (±39.3%) i/s -     15.338M

Comparison:
         "foo" "bar":  3940928.7 i/s
       String#append:  2238767.2 i/s - 1.76x slower
       String#concat:  2078496.3 i/s - 1.90x slower
            String#+:  1581525.0 i/s - 2.49x slower

end-string-checking-match-vs-end_with

require 'benchmark/ips'

SLUG = 'root_url'

def slow
  SLUG =~ /_(path|url)$/
end

def fast
  SLUG.end_with?('_path', '_url')
end

Benchmark.ips do |x|
  x.report('String#=~')        { slow }
  x.report('String#end_with?') { fast }
  x.compare!
end
Calculating -------------------------------------
           String#=~    35.185k i/100ms
    String#end_with?    60.894k i/100ms
-------------------------------------------------
           String#=~    713.267k (±31.9%) i/s -      3.167M
    String#end_with?      2.152M (±42.4%) i/s -      8.586M

Comparison:
    String#end_with?:  2151741.5 i/s
           String#=~:   713267.0 i/s - 3.02x slower

gsub-vs-sub

require 'benchmark/ips'

URL = 'http://www.thelongestlistofthelongeststuffatthelongestdomainnameatlonglast.com/wearejustdoingthistobestupidnowsincethiscangoonforeverandeverandeverbutitstilllookskindaneatinthebrowsereventhoughitsabigwasteoftimeandenergyandhasnorealpointbutwehadtodoitanyways.html'

def slow
  URL.gsub('http://', 'https://')
end

def fast
  URL.sub('http://', 'https://')
end

Benchmark.ips do |x|
  x.report('String#gsub') { slow }
  x.report('String#sub')  { fast }
  x.compare!
end
Calculating -------------------------------------
         String#gsub    26.927k i/100ms
          String#sub    28.941k i/100ms
-------------------------------------------------
         String#gsub    400.677k (±25.7%) i/s -      1.885M
          String#sub    501.270k (±29.8%) i/s -      2.286M

Comparison:
          String#sub:   501270.5 i/s
         String#gsub:   400677.2 i/s - 1.25x slower

gsub-vs-tr

require 'benchmark/ips'

SLUG = 'writing-fast-ruby'

def slow
  SLUG.gsub('-', ' ')
end

def fast
  SLUG.tr('-', ' ')
end

Benchmark.ips do |x|
  x.report('String#gsub') { slow }
  x.report('String#tr')   { fast }
  x.compare!
end
Calculating -------------------------------------
         String#gsub    23.616k i/100ms
           String#tr    52.470k i/100ms
-------------------------------------------------
         String#gsub    334.922k (±32.9%) i/s -      1.511M
           String#tr      1.286M (±41.6%) i/s -      5.404M

Comparison:
           String#tr:  1286379.5 i/s
         String#gsub:   334921.9 i/s - 3.84x slower

match-vs-=~

require 'benchmark/ips'

def fast
  "foo".freeze =~ /boo/
end

def slow
  "foo".freeze.match(/boo/)
end

Benchmark.ips do |x|
  x.report("String#=~") { fast }
  x.report("String#match") { slow }
  x.compare!
end
Calculating -------------------------------------
           String#=~    60.634k i/100ms
        String#match    62.773k i/100ms
-------------------------------------------------
           String#=~      1.931M (±26.9%) i/s -      8.610M
        String#match      1.528M (±23.7%) i/s -      7.093M

Comparison:
           String#=~:  1931237.4 i/s
        String#match:  1527869.6 i/s - 1.26x slower

start-string-checking-match-vs-start_with

require 'benchmark/ips'

SLUG = 'test_reverse_merge.rb'

def slow
  SLUG =~ /^test_/
end

def fast
  SLUG.start_with?('test_')
end

Benchmark.ips do |x|
  x.report('String#=~')          { slow }
  x.report('String#start_with?') { fast }
  x.compare!
end
Calculating -------------------------------------
           String#=~    35.188k i/100ms
  String#start_with?    69.012k i/100ms
-------------------------------------------------
           String#=~    704.836k (±30.2%) i/s -      3.167M
  String#start_with?      3.384M (±35.4%) i/s -     13.526M

Comparison:
  String#start_with?:  3384121.5 i/s
           String#=~:   704835.9 i/s - 4.80x slower

sub!-vs-gsub!-vs-[]=

require "benchmark/ips"

URL = "http://www.thelongestlistofthelongeststuffatthelongestdomainnameatlonglast.com/wearejustdoingthistobestupidnowsincethiscangoonforeverandeverandeverbutitstilllookskindaneatinthebrowsereventhoughitsabigwasteoftimeandenergyandhasnorealpointbutwehadtodoitanyways.html"

def fast
  s = URL.dup
  s["http://"] = ""
end

def slow_1
  s = URL.dup
  s.sub! "http://", ""
end

def slow_2
  s = URL.dup
  s.gsub! "http://", ""
end

def slow_3
  s = URL.dup
  s[%r{http://}] = ""
end

def slow_4
  s = URL.dup
  s.sub! %r{http://}, ""
end

def slow_5
  s = URL.dup
  s.gsub! %r{http://}, ""
end


Benchmark.ips do |x|
  x.report("String#['string']=")   { fast   }
  x.report("String#sub!'string'")  { slow_1 }
  x.report("String#gsub!'string'") { slow_2 }
  x.report("String#[/regexp/]=")   { slow_3 }
  x.report("String#sub!/regexp/")  { slow_4 }
  x.report("String#gsub!/regexp/") { slow_5 }
  x.compare!
end
Calculating -------------------------------------
  String#['string']=    44.383k i/100ms
 String#sub!'string'    32.853k i/100ms
String#gsub!'string'    22.916k i/100ms
  String#[/regexp/]=    34.780k i/100ms
 String#sub!/regexp/    30.148k i/100ms
String#gsub!/regexp/    17.308k i/100ms
-------------------------------------------------
  String#['string']=    721.316k (±31.7%) i/s -      3.284M
 String#sub!'string'    481.805k (±28.3%) i/s -      2.267M
String#gsub!'string'    313.836k (±26.3%) i/s -      1.467M
  String#[/regexp/]=    495.138k (±29.3%) i/s -      2.295M
 String#sub!/regexp/    381.125k (±26.1%) i/s -      1.779M
String#gsub!/regexp/    225.480k (±23.7%) i/s -      1.073M

Comparison:
  String#['string']=:   721315.9 i/s
  String#[/regexp/]=:   495138.2 i/s - 1.46x slower
 String#sub!'string':   481805.3 i/s - 1.50x slower
 String#sub!/regexp/:   381124.7 i/s - 1.89x slower
String#gsub!'string':   313836.1 i/s - 2.30x slower
String#gsub!/regexp/:   225479.5 i/s - 3.20x slower

合わせて読みたい

参考元


JuanitoFatas/fast-ruby