Created
February 14, 2016 10:30
-
-
Save pascalbetz/05972b4aab6d5a948c8a to your computer and use it in GitHub Desktop.
Compare BigDecimal implementations of Hanami Utils
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'benchmark/ips' | |
require 'bigdecimal' | |
VALUES = ['100.123', 100.123, '100', 100, Rational(1), Rational(4,1), Rational(0.3), BigDecimal.new('758.3'), 13289301283 ** 2, 0xf5] | |
module Hanami | |
module Utils | |
module Kernel | |
NUMERIC_MATCHER = /\A([\d\/\.\+iE]+|NaN|Infinity)\z/.freeze | |
def self.BigDecimalGem(arg) | |
case arg | |
when ->(a) { a.respond_to?(:to_d) } then arg.to_d | |
when Float, Complex, Rational | |
BigDecimal(arg.to_s) | |
when ->(a) { a.to_s.match(NUMERIC_MATCHER) } | |
BigDecimal.new(arg) | |
else | |
raise TypeError.new "can't convert #{inspect_type_error(arg)}into BigDecimal" | |
end | |
rescue NoMethodError | |
raise TypeError.new "can't convert #{inspect_type_error(arg)}into BigDecimal" | |
end | |
def self.BigDecimalMaster(arg) | |
case arg | |
when Numeric | |
BigDecimal(arg.to_s) | |
when ->(a) { a.respond_to?(:to_d) } | |
arg.to_d | |
else | |
BigDecimal.new(arg) | |
end | |
rescue NoMethodError | |
raise TypeError.new "can't convert #{inspect_type_error(arg)}into BigDecimal" | |
end | |
def self.BigDecimalIfWithIsA(arg) | |
if arg.is_a?(Numeric) | |
BigDecimal(arg.to_s) | |
elsif arg.respond_to?(:to_d) | |
arg.to_d | |
else | |
BigDecimal.new(arg) | |
end | |
rescue NoMethodError | |
raise TypeError.new "can't convert #{inspect_type_error(arg)}into BigDecimal" | |
end | |
def self.inspect_type_error(arg) | |
(arg.respond_to?(:inspect) ? arg.inspect : arg.to_s) << " " | |
rescue NoMethodError => _ | |
# missing the #respond_to? method, fall back to returning the class' name | |
begin | |
arg.class.name << " instance " | |
rescue NoMethodError | |
# missing the #class method, can't fall back to anything better than nothing | |
# Callers will have to guess from their code | |
nil | |
end | |
end | |
end | |
end | |
end | |
same_results = VALUES.map do |value| | |
[:BigDecimalIfWithIsA, :BigDecimalMaster, :BigDecimalGem].map do |method| | |
Hanami::Utils::Kernel.send(method, value)# rescue TypeError | |
end.uniq.size | |
end.uniq.size == 1 | |
p same_results | |
Benchmark.ips do |x| | |
x.report('master') do | |
VALUES.each do |value| | |
Hanami::Utils::Kernel.BigDecimalMaster(value)# rescue TypeError | |
end | |
end | |
x.report('gem') do | |
VALUES.each do |value| | |
Hanami::Utils::Kernel.BigDecimalGem(value)# rescue TypeError | |
end | |
end | |
x.report('if is a') do | |
VALUES.each do |value| | |
Hanami::Utils::Kernel.BigDecimalIfWithIsA(value)# rescue TypeError | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
master 5.134k i/100ms | |
gem 1.068k i/100ms | |
if is a 5.222k i/100ms | |
------------------------------------------------- | |
master 50.411k (±15.0%) i/s - 246.432k | |
gem 12.127k (± 4.1%) i/s - 60.876k | |
if is a 62.785k (± 6.0%) i/s - 313.320k |
@pascalbetz Thank you, I've got the following results:
ruby-2.3.0 ➜ ruby bench.rb
true
Calculating -------------------------------------
master 7.136k i/100ms
gem 1.798k i/100ms
if is a 7.911k i/100ms
-------------------------------------------------
master 78.095k (± 2.5%) i/s - 392.480k
gem 18.945k (± 1.8%) i/s - 95.294k
if is a 85.723k (± 1.8%) i/s - 435.105k
Comparison:
if is a: 85722.7 i/s
master: 78095.0 i/s - 1.10x slower
gem: 18944.8 i/s - 4.52x slower
ruby-2.2.4 ➜ ruby bench.rb
true
Warming up --------------------------------------
master 6.935k i/100ms
gem 1.776k i/100ms
if is a 7.841k i/100ms
Calculating -------------------------------------
master 75.573k (± 2.7%) i/s - 381.425k
gem 19.015k (± 2.1%) i/s - 95.904k
if is a 84.080k (± 2.5%) i/s - 423.414k
Comparison:
if is a: 84080.5 i/s
master: 75572.7 i/s - 1.11x slower
gem: 19014.9 i/s - 4.42x slower
jruby-9.0.5.0 ➜ ruby bench.rb
true
Warming up --------------------------------------
master 2.091k i/100ms
if is a 4.426k i/100ms
Calculating -------------------------------------
master 54.872k (± 5.5%) i/s - 273.921k
if is a 56.162k (± 5.5%) i/s - 283.264k
Comparison:
if is a: 56161.7 i/s
master: 54871.7 i/s - same-ish: difference falls within error
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Results for JRuby 9.0.5.0:
Warming up --------------------------------------
master 2.211k i/100ms
if is a 3.234k i/100ms
Calculating -------------------------------------
master 37.474k (± 5.1%) i/s - 187.935k
if is a 38.282k (± 4.6%) i/s - 190.806k