Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bkuhlmann/benchmarks
A collection of micro benchmarks.
https://github.com/bkuhlmann/benchmarks
benchmark micro speed
Last synced: 2 months ago
JSON representation
A collection of micro benchmarks.
- Host: GitHub
- URL: https://github.com/bkuhlmann/benchmarks
- Owner: bkuhlmann
- License: other
- Created: 2019-02-02T00:22:51.000Z (almost 6 years ago)
- Default Branch: main
- Last Pushed: 2024-05-27T22:58:17.000Z (8 months ago)
- Last Synced: 2024-05-28T08:21:19.812Z (8 months ago)
- Topics: benchmark, micro, speed
- Language: Ruby
- Homepage: https://alchemists.io/projects/benchmarks
- Size: 521 KB
- Stars: 5
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.adoc
- Funding: .github/FUNDING.yml
- License: LICENSE.adoc
- Citation: CITATION.cff
Awesome Lists containing this project
README
:toc: macro
:toclevels: 5
:figure-caption!:= Benchmarks
Benchmarks is a collection of Ruby micro benchmarks which can be cloned and run locally or used as
an information point of reference. The various statistics on Ruby performance captured within this
project may or may not surprise you.toc::[]
== Features
* Uses link:https://github.com/evanphx/benchmark-ips[Benchmark IPS] to calculate CPU/speed results.
* Each script is independently executable.== Requirements
. link:https://www.ruby-lang.org[Ruby]
== Setup
To install, run:
[source,bash]
----
git clone https://github.com/bkuhlmann/benchmarks.git
cd benchmarks
git checkout 4.9.0
bin/setup
----== Usage
All benchmark scripts are found within the `scripts` folder and you can run any benchmark using a relative or absolute file path. Example:
=== scripts/arrays/concatenation
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
enda = %w[one two three]
b = %w[four five six]Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "#+" do
a + b
endbenchmark.report "#+=" do
duplicate = a.dup
duplicate += b
endbenchmark.report "#concat" do
a.dup.concat b
endbenchmark.report "#|" do
a | b
endbenchmark.report "#<< + #flatten" do
(a.dup << b).flatten
endbenchmark.report "splat + #flatten" do
[a, *b].flatten
endbenchmark.report "multi-splat" do
[*a, *b]
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
#+ 1.109M i/100ms
#+= 642.208k i/100ms
#concat 640.592k i/100ms
#| 462.891k i/100ms
#<< + #flatten 190.264k i/100ms
splat + #flatten 191.960k i/100ms
multi-splat 595.693k i/100ms
Calculating -------------------------------------
#+ 11.380M (± 6.3%) i/s - 57.673M in 5.088056s
#+= 7.020M (± 7.5%) i/s - 35.321M in 5.060801s
#concat 6.757M (± 4.3%) i/s - 33.951M in 5.033526s
#| 4.589M (± 7.1%) i/s - 23.145M in 5.069256s
#<< + #flatten 1.995M (± 7.8%) i/s - 10.084M in 5.083410s
splat + #flatten 1.987M (± 7.7%) i/s - 9.982M in 5.053069s
multi-splat 6.018M (± 5.4%) i/s - 30.380M in 5.063797sComparison:
#+: 11379928.4 i/s
#+=: 7020046.0 i/s - 1.62x slower
#concat: 6757373.6 i/s - 1.68x slower
multi-splat: 6017673.7 i/s - 1.89x slower
#|: 4588614.9 i/s - 2.48x slower
#<< + #flatten: 1995390.6 i/s - 5.70x slower
splat + #flatten: 1986837.6 i/s - 5.73x slower
....=== scripts/arrays/search
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endlist = %w[one two three four five six seven eight nine ten]
pattern = /t/Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("#grep") { list.grep pattern }
benchmark.report("#select") { list.select { |value| value.match? pattern } }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
#grep 173.406k i/100ms
#select 185.779k i/100ms
Calculating -------------------------------------
#grep 1.771M (± 6.7%) i/s - 8.844M in 5.016015s
#select 1.912M (± 5.5%) i/s - 9.661M in 5.067631sComparison:
#select: 1912344.1 i/s
#grep: 1770866.9 i/s - same-ish: difference falls within error
....=== scripts/bindings
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"
gem "benchmark-ips"
endmodule Test
def self.with_binding(end:) = binding.local_variable_get(:end)def self.with_pinning(end:) = {end:}[:end]
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Binding") { Test.with_binding end: 1 }
benchmark.report("Pinning") { Test.with_pinning end: 1 }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23.5.0]
Warming up --------------------------------------
Binding 761.490k i/100ms
Pinning 2.104M i/100ms
Calculating -------------------------------------
Binding 7.991M (± 2.0%) i/s - 40.359M in 5.052741s
Pinning 24.189M (± 1.3%) i/s - 122.019M in 5.045416sComparison:
Pinning: 24188558.7 i/s
Binding: 7990579.0 i/s - 3.03x slower
....=== scripts/closures
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endExample = Class.new do
def echo_implicit text
yield
text
enddef echo_implicit_guard text
yield if block_given?
text
enddef echo_explicit text, &block
yield block
text
enddef echo_explicit_guard text, &block
yield block if block
text
end
endblock_example = Example.new
lambda_example = -> text { text }
proc_example = proc { |text| text }Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "Block (implicit)" do
block_example.echo_implicit("hi") { "test" }
endbenchmark.report "Block (implicit guard)" do
block_example.echo_implicit_guard("hi") { "test" }
endbenchmark.report "Block (explicit)" do
block_example.echo_explicit("hi") { "test" }
endbenchmark.report "Block (explicit guard)" do
block_example.echo_explicit_guard("hi") { "test" }
endbenchmark.report "Lambda" do
lambda_example.call "test"
endbenchmark.report "Proc" do
proc_example.call "test"
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Block (implicit) 3.719M i/100ms
Block (implicit guard)
3.997M i/100ms
Block (explicit) 595.448k i/100ms
Block (explicit guard)
597.963k i/100ms
Lambda 2.428M i/100ms
Proc 2.563M i/100ms
Calculating -------------------------------------
Block (implicit) 59.804M (± 1.0%) i/s - 301.203M in 5.037053s
Block (implicit guard)
59.083M (± 1.2%) i/s - 295.765M in 5.006599s
Block (explicit) 6.377M (± 6.6%) i/s - 32.154M in 5.065513s
Block (explicit guard)
6.365M (± 5.7%) i/s - 32.290M in 5.090170s
Lambda 34.880M (± 1.2%) i/s - 174.833M in 5.013192s
Proc 35.295M (± 1.9%) i/s - 176.865M in 5.012838sComparison:
Block (implicit): 59803662.6 i/s
Block (implicit guard): 59083369.8 i/s - same-ish: difference falls within error
Proc: 35294734.0 i/s - 1.69x slower
Lambda: 34879827.8 i/s - 1.71x slower
Block (explicit): 6377470.8 i/s - 9.38x slower
Block (explicit guard): 6365264.1 i/s - 9.40x slower
....=== scripts/constants/lookup
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endCONSTANTS = Hash.new
module Constants
1_000.times { |index| CONSTANTS["EXAMPLE_#{index}"] = const_set "EXAMPLE_#{index}", index }
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("#[]") { CONSTANTS["EXAMPLE_666"] }
benchmark.report("Module.get (symbol)") { Constants.const_get :EXAMPLE_666 }
benchmark.report("Module.get (string)") { Constants.const_get "EXAMPLE_666" }
benchmark.report("Object.get") { Object.const_get "Constants::EXAMPLE_666" }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
#[] 3.380M i/100ms
Module.get (symbol) 3.491M i/100ms
Module.get (string) 1.706M i/100ms
Object.get 1.068M i/100ms
Calculating -------------------------------------
#[] 44.355M (± 0.2%) i/s - 223.075M in 5.029360s
Module.get (symbol) 44.370M (± 0.1%) i/s - 223.435M in 5.035747s
Module.get (string) 18.818M (± 0.5%) i/s - 95.510M in 5.075490s
Object.get 11.076M (± 0.3%) i/s - 55.527M in 5.013445sComparison:
Module.get (symbol): 44369850.1 i/s
#[]: 44354632.8 i/s - same-ish: difference falls within error
Module.get (string): 18818346.2 i/s - 2.36x slower
Object.get: 11075724.0 i/s - 4.01x slower
....=== scripts/delegates
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endrequire "delegate"
require "forwardable"module Echo
def self.call(message) = message
endclass ForwardExample
def initialize operation
@operation = operation
enddef call(...) = operation.call(...)
private
attr_reader :operation
endclass DelegateExample
extend Forwardabledelegate %i[call] => :operation
def initialize operation
@operation = operation
endprivate
attr_reader :operation
endclass SimpleExample < SimpleDelegator
endclass ClassExample < DelegateClass Echo
endmessage = "A test."
forward_example = ForwardExample.new Echo
deletate_example = DelegateExample.new Echo
simple_example = SimpleExample.new Echo
class_example = ClassExample.new EchoBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Forward") { forward_example.call message }
benchmark.report("Delegate") { deletate_example.call message }
benchmark.report("Simple Delegator") { simple_example.call message }
benchmark.report("Delegate Class") { class_example.call message }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Forward 1.132M i/100ms
Delegate 1.017M i/100ms
Simple Delegator 385.198k i/100ms
Delegate Class 381.099k i/100ms
Calculating -------------------------------------
Forward 13.380M (± 5.3%) i/s - 66.769M in 5.005398s
Delegate 12.486M (± 3.0%) i/s - 63.053M in 5.054667s
Simple Delegator 4.191M (± 7.0%) i/s - 21.186M in 5.077130s
Delegate Class 4.174M (± 6.5%) i/s - 20.960M in 5.041277sComparison:
Forward: 13380268.0 i/s
Delegate: 12486453.4 i/s - same-ish: difference falls within error
Simple Delegator: 4191347.1 i/s - 3.19x slower
Delegate Class: 4174068.4 i/s - 3.21x slower
....=== scripts/hashes/lookup
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endexample = {a: 1, b: 2, c: 3}
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("#[]") { example[:b] }
benchmark.report("#fetch") { example.fetch :b }
benchmark.report("#fetch (default)") { example.fetch :b, "default" }
benchmark.report("#fetch (block)") { example.fetch(:b) { "default" } }
benchmark.report("#dig") { example.dig :b }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
#[] 4.035M i/100ms
#fetch 3.642M i/100ms
#fetch (default) 3.661M i/100ms
#fetch (block) 3.639M i/100ms
#dig 3.747M i/100ms
Calculating -------------------------------------
#[] 53.886M (± 0.1%) i/s - 270.328M in 5.016651s
#fetch 45.478M (± 0.1%) i/s - 229.440M in 5.045124s
#fetch (default) 45.677M (± 0.4%) i/s - 230.660M in 5.049861s
#fetch (block) 44.675M (± 0.2%) i/s - 225.636M in 5.050641s
#dig 50.390M (± 0.5%) i/s - 254.823M in 5.057135sComparison:
#[]: 53886256.9 i/s
#dig: 50390168.1 i/s - 1.07x slower
#fetch (default): 45677292.4 i/s - 1.18x slower
#fetch: 45477689.6 i/s - 1.18x slower
#fetch (block): 44674922.3 i/s - 1.21x slower
....=== scripts/hashes/merge
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endextra = {b: 2}
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Splat") { {a: 1, **extra} }
benchmark.report("Merge") { {a: 1}.merge extra }
benchmark.report("Merge!") { {a: 1}.merge! extra }
benchmark.report("Dup Merge!") { {a: 1}.dup.merge! extra }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Splat 977.474k i/100ms
Merge 651.230k i/100ms
Merge! 979.604k i/100ms
Dup Merge! 525.213k i/100ms
Calculating -------------------------------------
Splat 10.458M (± 7.0%) i/s - 52.784M in 5.072085s
Merge 6.637M (± 2.2%) i/s - 33.213M in 5.006663s
Merge! 10.624M (± 6.7%) i/s - 53.878M in 5.093783s
Dup Merge! 5.400M (± 7.0%) i/s - 27.311M in 5.081979sComparison:
Merge!: 10624192.6 i/s
Splat: 10457715.9 i/s - same-ish: difference falls within error
Merge: 6636870.8 i/s - 1.60x slower
Dup Merge!: 5399502.4 i/s - 1.97x slower
....=== scripts/hashes/reduce
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endnumbers = {
one: 1,
two: 2,
three: 3,
four: 4,
five: 5,
six: 6,
seven: 7,
eight: 8,
nine: 9,
ten: 10
}Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "Reduce" do
numbers.reduce({}) { |collection, (key, value)| collection.merge! value => key }
endbenchmark.report "With Object" do
numbers.each.with_object({}) { |(key, value), collection| collection[value] = key }
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Reduce 46.696k i/100ms
With Object 86.950k i/100ms
Calculating -------------------------------------
Reduce 469.369k (± 7.1%) i/s - 2.381M in 5.099251s
With Object 893.855k (± 0.5%) i/s - 4.521M in 5.058420sComparison:
With Object: 893855.0 i/s
Reduce: 469368.6 i/s - 1.90x slower
....=== scripts/loops
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endcollection = (1..1_000).to_a
sum = 0Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "for" do
for number in collection do
sum += number
end
endbenchmark.report "#each" do
collection.each { |number| sum += number }
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
for 6.369k i/100ms
#each 6.583k i/100ms
Calculating -------------------------------------
for 63.745k (± 0.1%) i/s - 324.819k in 5.095574s
#each 65.617k (± 0.5%) i/s - 329.150k in 5.016325sComparison:
#each: 65617.4 i/s
for: 63745.4 i/s - 1.03x slower
....=== scripts/methods/define_method
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endrequire "forwardable"
Person = Class.new do
def initialize first, last
@first = first
@last = last
enddef full_name
"#{first} #{last}"
endprivate
attr_reader :first, :last
endExample = Class.new Person do
extend Forwardabledefine_method :unbound_full_name, Person.instance_method(:full_name)
delegate %i[full_name] => :persondef initialize first, last, person: Person.new(first, last)
super first, last
@person = person
enddef wrapped_full_name
person.full_name
endprivate
attr_reader :first, :last, :person
endexample = Example.new "Jill", "Doe"
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Wrapped") { example.wrapped_full_name }
benchmark.report("Defined") { example.unbound_full_name }
benchmark.report("Delegated") { example.full_name }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Wrapped 1.128M i/100ms
Defined 1.153M i/100ms
Delegated 626.507k i/100ms
Calculating -------------------------------------
Wrapped 12.039M (± 4.8%) i/s - 60.917M in 5.072433s
Defined 12.270M (± 3.9%) i/s - 62.244M in 5.080966s
Delegated 6.912M (± 6.2%) i/s - 34.458M in 5.005586sComparison:
Defined: 12269954.3 i/s
Wrapped: 12039424.1 i/s - same-ish: difference falls within error
Delegated: 6912331.3 i/s - 1.78x slower
....=== scripts/methods/method_proc
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endExample = Class.new do
def initialize words
@words = words
@first_word = words.first
enddef direct_single
say first_word
enddef direct_multiple
words.each { |word| say word }
enddef proc_single
method(:say).call first_word
enddef proc_multiple
words.each { |word| method(:say).call word }
enddef method_to_proc_single
first_word.then(&method(:say))
enddef method_to_proc_multiple
words.each(&method(:say))
endprivate
attr_reader :words, :first_word
def say phrase
"You said: #{phrase}."
end
endexample = Example.new %w[one two three]
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Direct (s)") { example.direct_single }
benchmark.report("Direct (m)") { example.direct_multiple }
benchmark.report("Proc (s)") { example.proc_single }
benchmark.report("Proc (m)") { example.proc_multiple }
benchmark.report("Method To Proc (s)") { example.method_to_proc_single }
benchmark.report("Method To Proc (m)") { example.method_to_proc_multiple }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Direct (s) 1.154M i/100ms
Direct (m) 391.284k i/100ms
Proc (s) 547.383k i/100ms
Proc (m) 167.519k i/100ms
Method To Proc (s) 260.729k i/100ms
Method To Proc (m) 176.733k i/100ms
Calculating -------------------------------------
Direct (s) 12.832M (± 4.1%) i/s - 64.611M in 5.043941s
Direct (m) 4.159M (± 4.2%) i/s - 21.129M in 5.088977s
Proc (s) 6.454M (± 6.0%) i/s - 32.296M in 5.023367s
Proc (m) 1.830M (± 3.9%) i/s - 9.214M in 5.043206s
Method To Proc (s) 2.874M (± 3.4%) i/s - 14.601M in 5.086253s
Method To Proc (m) 1.962M (± 3.3%) i/s - 9.897M in 5.048962sComparison:
Direct (s): 12831929.9 i/s
Proc (s): 6453824.9 i/s - 1.99x slower
Direct (m): 4158707.8 i/s - 3.09x slower
Method To Proc (s): 2874279.1 i/s - 4.46x slower
Method To Proc (m): 1962181.8 i/s - 6.54x slower
Proc (m): 1829728.8 i/s - 7.01x slower
....=== scripts/methods/send
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endmodule Static
def self.call = rand > 0.5 ? one : twodef self.one = 1
def self.two = 2
endmodule Dynamic
def self.with_strings = public_send rand > 0.5 ? "one" : "two"def self.with_symbols = public_send rand > 0.5 ? :one : :two
def self.one = 1
def self.two = 2
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2
max = 1_000_000benchmark.report("Static") { max.times { Static.call } }
benchmark.report("Dynamic (strings)") { max.times { Dynamic.with_strings } }
benchmark.report("Dynamic (symbols)") { max.times { Dynamic.with_symbols } }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Static 2.000 i/100ms
Dynamic (strings) 1.000 i/100ms
Dynamic (symbols) 1.000 i/100ms
Calculating -------------------------------------
Static 27.041 (± 0.0%) i/s - 136.000 in 5.029371s
Dynamic (strings) 11.600 (± 0.0%) i/s - 59.000 in 5.086066s
Dynamic (symbols) 15.589 (± 0.0%) i/s - 78.000 in 5.003651sComparison:
Static: 27.0 i/s
Dynamic (symbols): 15.6 i/s - 1.73x slower
Dynamic (strings): 11.6 i/s - 2.33x slower
....=== scripts/numerics
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "bigdecimal"
gem "benchmark-ips"
endrequire "bigdecimal"
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Integer") { 1 + 0 }
benchmark.report("Float") { 0.0001 + 0 }
benchmark.report("Rational") { (1 / 1000r) + 0 }
benchmark.report("BigDecimal") { BigDecimal("0.0001") + 0 }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Integer 4.945M i/100ms
Float 3.898M i/100ms
Rational 957.175k i/100ms
BigDecimal 226.746k i/100ms
Calculating -------------------------------------
Integer 75.084M (± 4.5%) i/s - 375.824M in 5.021257s
Float 60.640M (± 0.6%) i/s - 304.039M in 5.013994s
Rational 10.254M (± 0.6%) i/s - 51.687M in 5.040700s
BigDecimal 2.332M (± 4.5%) i/s - 11.791M in 5.066520sComparison:
Integer: 75083686.6 i/s
Float: 60640359.1 i/s - 1.24x slower
Rational: 10254439.4 i/s - 7.32x slower
BigDecimal: 2332151.1 i/s - 32.20x slower
....=== scripts/pattern_matching/multiple_type_check
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"
gem "benchmark-ips"
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("include?") { [String, Symbol].include? :test.class }
benchmark.report("in") { :test in String | Symbol }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) +YJIT [arm64-darwin23.6.0]
Warming up --------------------------------------
include? 2.133M i/100ms
in 2.125M i/100ms
Calculating -------------------------------------
include? 24.603M (± 1.5%) i/s (40.65 ns/i) - 123.710M in 5.029399s
in 26.547M (± 1.7%) i/s (37.67 ns/i) - 133.855M in 5.043962sComparison:
in: 26546608.0 i/s
include?: 24602944.9 i/s - 1.08x slower
....=== scripts/pattern_matching/single_type_check
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"
gem "benchmark-ips"
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("is_a?") { :test.is_a? Symbol }
benchmark.report("in") { :test in Symbol }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.5 (2024-09-03 revision ef084cc8f4) +YJIT [arm64-darwin23.6.0]
Warming up --------------------------------------
is_a? 4.544M i/100ms
in 3.022M i/100ms
Calculating -------------------------------------
is_a? 72.453M (± 0.5%) i/s (13.80 ns/i) - 363.542M in 5.017741s
in 39.524M (± 2.1%) i/s (25.30 ns/i) - 199.473M in 5.049727sComparison:
is_a?: 72453047.7 i/s
in: 39523743.1 i/s - 1.83x slower
....=== scripts/refinements/import
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endmodule Import
def dud = true
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "With" do
Module.new { refine(String) { import_methods Import } }
endbenchmark.report "Without" do
Module.new { def dud = true }
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
With 1.438k i/100ms
Without 365.822k i/100ms
Calculating -------------------------------------
With 21.970k (±190.8%) i/s - 43.140k in 5.067653s
Without 3.636M (± 7.1%) i/s - 18.291M in 5.054830sComparison:
Without: 3635623.1 i/s
With: 21969.9 i/s - 165.48x slower
....=== scripts/refinements/initialize
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endmodule Refines
refine String do
def dud = true
end
endclass With
using Refinesdef initialize value = "demo"
@value = value
end
endclass Without
def initialize value = "demo"
@value = value
end
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("With") { With.new }
benchmark.report("Without") { Without.new }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
With 1.118M i/100ms
Without 1.067M i/100ms
Calculating -------------------------------------
With 12.286M (± 5.5%) i/s - 61.467M in 5.019067s
Without 11.971M (± 5.7%) i/s - 59.775M in 5.010076sComparison:
With: 12285927.1 i/s
Without: 11970917.9 i/s - same-ish: difference falls within error
....=== scripts/refinements/message
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endmodule Refines
refine String do
def dud = true
end
endmodule With
using Refinesdef self.call(value) = value.dud
endmodule Without
def self.call(value) = value
endvalue = "demo"
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("With") { With.call value }
benchmark.report("Without") { Without.call value }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
With 2.681M i/100ms
Without 3.796M i/100ms
Calculating -------------------------------------
With 37.893M (± 1.2%) i/s - 190.353M in 5.024141s
Without 59.787M (± 4.2%) i/s - 299.874M in 5.024598sComparison:
Without: 59786895.6 i/s
With: 37893449.5 i/s - 1.58x slower
....=== scripts/refinements/refine
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "With" do
Module.new do
refine String do
def dud = true
end
end
endbenchmark.report "Without" do
Module.new do
def dud = true
end
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
With 1.497k i/100ms
Without 337.437k i/100ms
Calculating -------------------------------------
With 21.225k (±192.4%) i/s - 35.928k in 5.093624s
Without 3.284M (± 8.5%) i/s - 16.534M in 5.067713sComparison:
Without: 3284418.0 i/s
With: 21224.8 i/s - 154.74x slower
....=== scripts/strings/concatenation
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endone = "One"
two = "Two"
three = "Three"
four = "Four"
five = "Five"
six = "Six"
seven = "Seven"
eight = "Eight"
nine = "Nine"
ten = "Ten"Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "Implicit (<)" do
"One" "Two"
endbenchmark.report "Implicit (>)" do
"One" "Two" "Three" "Four" "Five" "Six" "Seven" "Eight" "Nine" "Ten"
endbenchmark.report "Interpolation (<)" do
"#{one} #{two}"
endbenchmark.report "Interpolation (>)" do
"#{one} #{two} #{three} #{four} #{five} #{six} #{seven} #{eight} #{nine} #{ten}"
endbenchmark.report "#+ (<)" do
one + " " + two
endbenchmark.report "#+ (>)" do
one + " " + two + " " + three + " " + four + " " + five + " " + six + " " + seven + " " +
eight + " " + nine + " " + ten
end# WARNING: Mutation.
benchmark.report "#concat (<)" do
one.dup.concat two
end# WARNING: Mutation.
benchmark.report "#concat (>)" do
one.dup.concat two, three, four, five, six, seven, eight, nine, ten
end# WARNING: Mutation.
benchmark.report "#<< (<)" do
one.dup << two
end# WARNING: Mutation.
benchmark.report "#<< (>)" do
one.dup << two << three << four << five << six << seven << eight << nine << ten
endbenchmark.report "Array#join (<)" do
[one, two].join " "
endbenchmark.report "Array#join (>)" do
[one, two, three, four, five, six, seven, eight, nine, ten].join " "
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Implicit (<) 4.372M i/100ms
Implicit (>) 4.448M i/100ms
Interpolation (<) 1.208M i/100ms
Interpolation (>) 367.925k i/100ms
#+ (<) 823.216k i/100ms
#+ (>) 80.833k i/100ms
#concat (<) 1.369M i/100ms
#concat (>) 291.617k i/100ms
#<< (<) 1.479M i/100ms
#<< (>) 459.494k i/100ms
Array#join (<) 722.879k i/100ms
Array#join (>) 307.222k i/100ms
Calculating -------------------------------------
Implicit (<) 75.685M (± 1.7%) i/s - 380.338M in 5.026812s
Implicit (>) 75.105M (± 1.8%) i/s - 378.120M in 5.036297s
Interpolation (<) 12.722M (± 5.7%) i/s - 64.005M in 5.047960s
Interpolation (>) 3.868M (± 5.9%) i/s - 19.500M in 5.057509s
#+ (<) 8.701M (± 7.1%) i/s - 43.630M in 5.038462s
#+ (>) 837.724k (± 7.7%) i/s - 4.203M in 5.048670s
#concat (<) 14.496M (± 8.5%) i/s - 72.583M in 5.045357s
#concat (>) 2.959M (± 8.8%) i/s - 14.872M in 5.063294s
#<< (<) 15.944M (± 8.0%) i/s - 79.888M in 5.043131s
#<< (>) 4.739M (± 9.0%) i/s - 23.894M in 5.082877s
Array#join (<) 7.392M (± 7.9%) i/s - 36.867M in 5.018258s
Array#join (>) 3.275M (± 7.8%) i/s - 16.283M in 5.000238sComparison:
Implicit (<): 75684765.3 i/s
Implicit (>): 75104861.7 i/s - same-ish: difference falls within error
#<< (<): 15944068.0 i/s - 4.75x slower
#concat (<): 14496048.1 i/s - 5.22x slower
Interpolation (<): 12722385.9 i/s - 5.95x slower
#+ (<): 8700892.4 i/s - 8.70x slower
Array#join (<): 7392065.5 i/s - 10.24x slower
#<< (>): 4738942.8 i/s - 15.97x slower
Interpolation (>): 3867990.4 i/s - 19.57x slower
Array#join (>): 3274997.2 i/s - 23.11x slower
#concat (>): 2959275.8 i/s - 25.58x slower
#+ (>): 837724.4 i/s - 90.35x slower
....=== scripts/strings/matching
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endrequire "securerandom"
word = SecureRandom.alphanumeric 100
string_matcher = "a"
regex_matcher = /\Aa/Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("#match?") { word.match? regex_matcher }
benchmark.report("#=~") { word =~ regex_matcher }
benchmark.report("#start_with? (String)") { word.start_with? string_matcher }
benchmark.report("#start_with? (Regex)") { word.start_with? regex_matcher }
benchmark.report("#end_with?") { word.end_with? string_matcher }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
#match? 2.422M i/100ms
#=~ 742.580k i/100ms
#start_with? (String)
2.965M i/100ms
#start_with? (Regex) 679.369k i/100ms
#end_with? 3.069M i/100ms
Calculating -------------------------------------
#match? 28.797M (± 5.0%) i/s - 145.346M in 5.060238s
#=~ 7.620M (± 9.1%) i/s - 37.872M in 5.008839s
#start_with? (String)
34.312M (± 5.0%) i/s - 171.982M in 5.024675s
#start_with? (Regex) 7.464M (± 7.4%) i/s - 37.365M in 5.034025s
#end_with? 37.141M (± 0.5%) i/s - 187.219M in 5.040811sComparison:
#end_with?: 37141486.2 i/s
#start_with? (String): 34312493.3 i/s - 1.08x slower
#match?: 28797216.7 i/s - 1.29x slower
#=~: 7620209.0 i/s - 4.87x slower
#start_with? (Regex): 7463669.2 i/s - 4.98x slower
....=== scripts/strings/split
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endrequire "securerandom"
words = Array.new(100_000) { SecureRandom.alphanumeric 10 }
delimiter = " "
text = words.join delimiter
pattern = /\Aa/Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "Without Block" do
text.split(delimiter).grep(pattern)
endbenchmark.report "With Block" do
selections = []
text.split(delimiter) { |word| selections << word if word.match? pattern }
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Without Block 13.000 i/100ms
With Block 13.000 i/100ms
Calculating -------------------------------------
Without Block 136.799 (± 2.2%) i/s - 689.000 in 5.039420s
With Block 134.538 (± 2.2%) i/s - 676.000 in 5.026808sComparison:
Without Block: 136.8 i/s
With Block: 134.5 i/s - same-ish: difference falls within error
....=== scripts/strings/substrings
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endexample = "example"
Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("#sub (string)") { example.sub "x", "b" }
benchmark.report("#sub (regex)") { example.sub(/x/, "b") }
benchmark.report("#gsub (string)") { example.gsub "x", "b" }
benchmark.report("#gsub (regex)") { example.gsub(/x/, "b") }
benchmark.report("#tr") { example.tr "x", "b" }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
#sub (string) 484.505k i/100ms
#sub (regex) 344.692k i/100ms
#gsub (string) 414.555k i/100ms
#gsub (regex) 170.417k i/100ms
#tr 1.007M i/100ms
Calculating -------------------------------------
#sub (string) 5.449M (± 3.0%) i/s - 27.617M in 5.073218s
#sub (regex) 4.021M (± 6.1%) i/s - 20.337M in 5.074883s
#gsub (string) 4.463M (± 3.4%) i/s - 22.386M in 5.021307s
#gsub (regex) 1.710M (± 8.6%) i/s - 8.521M in 5.018878s
#tr 10.693M (± 2.8%) i/s - 54.352M in 5.087263sComparison:
#tr: 10692642.6 i/s
#sub (string): 5448640.0 i/s - 1.96x slower
#gsub (string): 4463049.2 i/s - 2.40x slower
#sub (regex): 4020798.1 i/s - 2.66x slower
#gsub (regex): 1710379.3 i/s - 6.25x slower
....=== scripts/thens
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report "standard" do
one, two = "one two".split
"#{one} + #{two} = #{one + two}"
endbenchmark.report "then" do
"one two".split.then { |one, two| "#{one} + #{two} = #{one + two}" }
endbenchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
standard 361.533k i/100ms
then 340.568k i/100ms
Calculating -------------------------------------
standard 3.566M (± 7.3%) i/s - 18.077M in 5.096489s
then 3.366M (± 7.6%) i/s - 17.028M in 5.088830sComparison:
standard: 3566064.8 i/s
then: 3365922.3 i/s - same-ish: difference falls within error
....=== scripts/values/inheritance
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endPlotStruct = Struct.new :x, :y
class PlotSubclass < Struct.new :x, :y
endstruct = -> { PlotStruct[x: 1, y: 2] }
subclass = -> { PlotSubclass[x: 1, y: 2] }Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Struct") { struct.call }
benchmark.report("Subclass") { subclass.call }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Struct 446.439k i/100ms
Subclass 438.472k i/100ms
Calculating -------------------------------------
Struct 4.925M (± 7.6%) i/s - 24.554M in 5.013174s
Subclass 4.736M (± 7.8%) i/s - 23.677M in 5.027862sComparison:
Struct: 4924540.0 i/s
Subclass: 4736109.1 i/s - same-ish: difference falls within error
....=== scripts/values/initialization
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
gem "dry-struct"
endWarning[:performance] = false
require "ostruct"
DataDefault = Data.define :a, :b, :c, :d, :e
DataCustom = Data.define :a, :b, :c, :d, :e do
def initialize a: 1, b: 2, c: 3, d: 4, e: 5
super
end
endStructDefault = Struct.new :a, :b, :c, :d, :e
StructCustom = Struct.new :a, :b, :c, :d, :e do
def initialize a: 1, b: 2, c: 3, d: 4, e: 5
super
end
endmodule Types
include Dry.Types
endDryExample = Class.new Dry::Struct do
attribute :a, Types::Strict::Integer
attribute :b, Types::Strict::Integer
attribute :c, Types::Strict::Integer
attribute :d, Types::Strict::Integer
attribute :e, Types::Strict::Integer
endBenchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Data (positional)") { DataDefault[1, 2, 3, 4, 5] }
benchmark.report("Data (keyword)") { DataDefault[a: 1, b: 2, c: 3, d: 4, e: 5] }
benchmark.report("Data (custom)") { DataCustom.new }
benchmark.report("Struct (positional)") { StructDefault[1, 2, 3, 4, 5] }
benchmark.report("Struct (keyword)") { StructDefault[a: 1, b: 2, c: 3, d: 4, e: 5] }
benchmark.report("Struct (custom)") { StructCustom.new }
benchmark.report("OpenStruct") { OpenStruct.new a: 1, b: 2, c: 3, d: 4, e: 5 }
benchmark.report("Dry Struct") { DryExample[a: 1, b: 2, c: 3, d: 4, e: 5] }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Data (positional) 304.848k i/100ms
Data (keyword) 317.019k i/100ms
Data (custom) 224.669k i/100ms
Struct (positional) 722.167k i/100ms
Struct (keyword) 302.062k i/100ms
Struct (custom) 292.850k i/100ms
OpenStruct 743.000 i/100ms
Dry Struct 111.304k i/100ms
Calculating -------------------------------------
Data (positional) 3.120M (± 9.7%) i/s - 15.547M in 5.025792s
Data (keyword) 3.191M (± 9.7%) i/s - 15.851M in 5.008582s
Data (custom) 2.226M (± 3.6%) i/s - 11.233M in 5.054091s
Struct (positional) 6.869M (±10.4%) i/s - 34.664M in 5.098769s
Struct (keyword) 3.059M (± 9.6%) i/s - 15.405M in 5.077727s
Struct (custom) 2.945M (±11.4%) i/s - 14.642M in 5.031281s
OpenStruct 1.856k (±24.0%) i/s - 9.659k in 5.485483s
Dry Struct 1.123M (±11.8%) i/s - 5.565M in 5.029750sComparison:
Struct (positional): 6868838.9 i/s
Data (keyword): 3191343.7 i/s - 2.15x slower
Data (positional): 3120155.8 i/s - 2.20x slower
Struct (keyword): 3059412.6 i/s - 2.25x slower
Struct (custom): 2945238.4 i/s - 2.33x slower
Data (custom): 2225751.7 i/s - 3.09x slower
Dry Struct: 1123063.3 i/s - 6.12x slower
OpenStruct: 1855.9 i/s - 3701.01x slowerℹ️ `Data` is fastest when members are small (like three or less) but performance degrades when more members are added (like five or more). This is because `Data` always initializes with a `Hash` which is not the case with a `Struct`. Additionally, passing keyword arguments to/from Ruby to Ruby is optimized while to/from Ruby/C is not.
....=== scripts/values/reading
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
gem "dry-struct"
endrequire "ostruct"
DataExample = Data.define :to, :from
StructExample = Struct.new :to, :frommodule Types
include Dry.Types
endDryExample = Class.new Dry::Struct do
attribute :to, Types::Strict::String
attribute :from, Types::Strict::String
enddata = DataExample[to: "Rick", from: "Morty"]
struct = StructExample[to: "Rick", from: "Morty"]
open_struct = OpenStruct.new to: "Rick", from: "Morty"
dry_struct = DryExample[to: "Rick", from: "Morty"]Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Data") { data.to }
benchmark.report("Struct") { struct.to }
benchmark.report("OpenStruct") { open_struct.to }
benchmark.report("Dry Struct") { dry_struct.to }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Data 4.313M i/100ms
Struct 3.960M i/100ms
OpenStruct 3.419M i/100ms
Dry Struct 3.646M i/100ms
Calculating -------------------------------------
Data 72.832M (± 0.1%) i/s - 366.637M in 5.034027s
Struct 68.730M (± 0.4%) i/s - 344.554M in 5.013242s
OpenStruct 49.555M (± 0.1%) i/s - 249.580M in 5.036400s
Dry Struct 49.635M (± 0.1%) i/s - 251.578M in 5.068604sComparison:
Data: 72831756.3 i/s
Struct: 68729971.7 i/s - 1.06x slower
Dry Struct: 49634683.0 i/s - 1.47x slower
OpenStruct: 49555343.3 i/s - 1.47x slower
....=== scripts/values/writing
*Source*
[source,ruby]
----
#! /usr/bin/env ruby
# frozen_string_literal: truerequire "bundler/inline"
gemfile true do
source "https://rubygems.org"gem "benchmark-ips"
endrequire "ostruct"
DataExample = Data.define :to, :from
StructExample = Struct.new :to, :fromdata = DataExample[to: "Rick", from: "Morty"]
struct = StructExample[to: "Rick", from: "Morty"]
open_struct = OpenStruct.new to: "Rick", from: "Morty"Benchmark.ips do |benchmark|
benchmark.config time: 5, warmup: 2benchmark.report("Data") { data.with from: "Summer" }
benchmark.report("Struct") { struct.from = "Summer" }
benchmark.report("OpenStruct") { open_struct.from = "Summer" }benchmark.compare!
end
----*Benchmark*
....
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT [arm64-darwin23.4.0]
Warming up --------------------------------------
Data 265.287k i/100ms
Struct 4.274M i/100ms
OpenStruct 2.870M i/100ms
Calculating -------------------------------------
Data 2.721M (± 8.0%) i/s - 13.530M in 5.002940s
Struct 55.482M (± 1.5%) i/s - 277.793M in 5.008024s
OpenStruct 34.810M (± 0.2%) i/s - 175.090M in 5.029864sComparison:
Struct: 55482353.9 i/s
OpenStruct: 34810159.3 i/s - 1.59x slower
Data: 2721426.3 i/s - 20.39x slower
....== Development
To contribute, run:
[source,bash]
----
git clone https://github.com/bkuhlmann/benchmarks.git
cd benchmarks
bin/setup
----To render documentation for all benchmark scripts, run:
[source,bash]
----
bin/render
----This is the same script used to update the documentation within this README.
== Tests
To test, run:
[source,bash]
----
bin/rake
----== link:https://alchemists.io/policies/license[License]
== link:https://alchemists.io/policies/security[Security]
== link:https://alchemists.io/policies/code_of_conduct[Code of Conduct]
== link:https://alchemists.io/policies/contributions[Contributions]
== link:https://alchemists.io/policies/developer_certificate_of_origin[Developer Certificate of Origin]
== link:https://alchemists.io/projects/benchmarks/versions[Versions]
== link:https://alchemists.io/community[Community]
== Credits
* Built with link:https://alchemists.io/projects/rubysmith[Rubysmith].
* Engineered by link:https://alchemists.io/team/brooke_kuhlmann[Brooke Kuhlmann].