34
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

はじめに

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

34
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?