Issue #7645 has been updated by shugo (Shugo Maeda).

Status changed from Closed to Open

mrkn (Kenta Murata) wrote:
> * numeric.c (do_coerce): speed optimization by using rb_check_funcall
>   instead of rb_rescue + rb_funcall.
>   This fix is based on the patch by Benoit Daloze.
>   [Bug #7645] [ruby-core:51213]

This change caused an error in RubySpec.

1)
Bignum#<=> with an Object returns nil if #coerce raises an exception ERROR
RuntimeError: RuntimeError
(eval):2:in `coerce'
/home/shugo/src/rubyspec/core/bignum/comparison_spec.rb:103:in `<=>'
/home/shugo/src/rubyspec/core/bignum/comparison_spec.rb:103:in `block (3 levels) in <top (required)>'
/home/shugo/src/rubyspec/core/bignum/comparison_spec.rb:3:in `<top (required)>'
/home/shugo/local/lib/ruby/gems/2.0.0/gems/mspec-1.5.17/bin/mspec-run:8:in `<main>'

The code around line 103 is as follows:

   101      it "returns nil if #coerce raises an exception" do
   102        @num.should_receive(:coerce).with(@big).and_raise(RuntimeError)
   103        (@big <=> @num).should be_nil
   104      end

Is it just an implementation detail or an intentional spec change?
If so, RubySpec should be changed.  Otherwise, please fix the behavior.

----------------------------------------
Bug #7645: BigDecimal#== slow when compared to true/false
https://bugs.ruby-lang.org/issues/7645#change-35317

Author: mathie (Graeme Mathieson)
Status: Open
Priority: Normal
Assignee: mrkn (Kenta Murata)
Category: 
Target version: 
ruby -v: ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-darwin12.2.0]


I was doing a spot of profiling on a Ruby on Rails application with perftools.rb and spotted that one particular chunk of code was spending a lot (nearly 60% in some tests) of its time in `BigDecimal#==`. It turns out that, when writing a numeric attribute in ActiveRecord, it compares the value to both `true` and `false`, and that appears to be the source of the slowness. I've reproduced this with the following sample code:

    require 'bigdecimal'

    1_000_000.times do
      BigDecimal('3') == true
    end

This snippet takes around 7 seconds to run on my Mac. If instead we compare with a number:

    require 'bigdecimal'

    1_000_000.times do
      BigDecimal('3') == 0
    end

the runtime drops to ~1.2 seconds. This seems suboptimal. I'm struggling to follow through the BigDecimal source code, but the profile output indicates that `BigDecimal#==` is causing a `NameError` exception to be raised, which it's then catching and returning a valid result.

I've reported this issue to the Rails tracker here: <https://github.com/rails/rails/issues/8673>. While there's an easy workaround for ActiveRecord (I hope, anyway!), it does strike me that BigDecimalCmp() could short-circuit and return something sensible if the comparison value is true, false or nil?

This is my first bug report to Ruby core, so apologies if it's not quite up to scratch. If you need any more information from me, please do ask. Thank you!


-- 
http://bugs.ruby-lang.org/