Skip to content

Instantly share code, notes, and snippets.

@pascalbetz
Created February 14, 2016 10:30
Show Gist options
  • Save pascalbetz/05972b4aab6d5a948c8a to your computer and use it in GitHub Desktop.
Save pascalbetz/05972b4aab6d5a948c8a to your computer and use it in GitHub Desktop.
Compare BigDecimal implementations of Hanami Utils
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
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
Copy link
Author

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

@jodosha
Copy link

jodosha commented Feb 15, 2016

@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