はじめに
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