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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@pascalbetz Thank you, I've got the following results: