Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9

#410

constantize in lib/active_support/inflector.rb uses eval which is slow in both JRuby and Ruby 1.9. This patch passes all tests and also significantly speeds up constantize on these ruby impl (without hurting perf of Ruby 1.8).

Reported by enebo · June 13th, 2008 @ 06:25 PM

State: open
Milestone: 3.0.6
Assigned to: Jeremy Kemper Jeremy Kemper
Importance: Low

Activity

  1. Chris Lloyd
    Chris Lloyd
    • Tag set to patch

    +1

    Passes all tests. I've attached a benchmark which shows this is actually slightly faster with simple constant names running 1.8.6.

    It slows down with multiple namespaces. Parity occurs with 3 nested namespaces (A::B::C) but the perf. difference on even up to 7 nested namespaces is minimal. Looks good.

    August 7th, 2008 @ 12:24 AM

  2. Repository
    Repository
    • State changed from new to resolved

    (from [88eec8327b179cd41314e85868879b46bcf2530e]) JRuby: improve constantize performance. [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:resolved] http://github.com/rails/rails/co...

    August 7th, 2008 @ 01:34 AM

  3. Repository
    Repository

    (from [ed8a882e47e07b470b71cacd8cd50e251dca4d27]) JRuby: improve constantize performance. [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:resolved] http://github.com/rails/rails/co...

    August 7th, 2008 @ 01:34 AM

  4. Jeremy Kemper
    Jeremy Kemper
    • Assigned user set to Jeremy Kemper
    • Tag changed from patch to activesupport, patch
    • Milestone set to 2.1.1

    August 7th, 2008 @ 01:36 AM

  5. Michael Johnston
    Michael Johnston

    This fails (after about 30 rounds of constantize / const_missing / parent)

    @@@ruby class Outer TOM=5 end

    module Bob class Mary

    class Foo < ::Outer
    end
    def self.doit
      i = ::Bob::Mary::Foo.new
      puts "dereference: #{::Bob::Mary::Foo::TOM}"
      puts [constantize: #{](:Bob::Mary::Foo::TOM".constantize}")
    end
    
    

    end end

    Bob::Mary.doit

    
    
    for an example in the wild see the init function of picnic
    

    September 11th, 2008 @ 08:36 AM

  6. Michael Johnston
    Michael Johnston

    sigh. lets try that again.

    
    class Outer
      TOM=5
    end
    
    module Bob
      class Mary
        class Foo < ::Outer
        end
        def self.doit
          i = ::Bob::Mary::Foo.new
          puts "dereference: #{::Bob::Mary::Foo::TOM}"
          puts "constantize: #{"::Bob::Mary::Foo::TOM".constantize}"
        end
      end
    end
    
    Bob::Mary.doit
    

    for an example in the wild see the init function of picnic

    September 11th, 2008 @ 08:37 AM

  7. Michael Johnston
    Michael Johnston

    actually, this fails too:

    
    class Outer2
      module Why
        TOM2 = 5
      end
      include Why
    end
    
    "Outer2::TOM2".constantize
    

    which is why "Logger::INFO".constantize fails which is (another reason) why picnic fails.

    September 11th, 2008 @ 08:51 AM

  8. Jeremy Kemper
    Jeremy Kemper
    • State changed from resolved to open

    Michael, could you add a failing test case? Do you have a workaround that doesn't use eval?

    September 11th, 2008 @ 05:08 PM

  9. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.1.1 to 2.1.3

    October 24th, 2008 @ 03:19 AM

  10. Ripta Pasay
    Ripta Pasay

    It's been awhile, so attached is my own attempt a failing test case. I added an "Extension" module to Ace::Base; it's the simplest I could come up with that fails. The "Extension" doesn't break the rest of the test cases.

    December 3rd, 2008 @ 04:46 PM

  11. Frederick Cheung
    Frederick Cheung

    This seems to do the trick, speed seems on par with the previous implementation. Not 100% sure about the ruby 1.9 specific changes, the inflector tests do still pass but I'm not quite up to date on how const_defined? etc.. have changed

    December 13th, 2008 @ 06:24 PM

  12. Frederick Cheung
    Frederick Cheung

    Oops, ruby 1.9 changes were a bit off. This should be better

    December 14th, 2008 @ 10:08 AM

  13. Repository
    Repository
    • State changed from open to resolved

    (from [eca79e6bf052041c018c7ba08750238f8b2ecb7a]) Make constantize look into ancestors

    [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:resolved]

    Signed-off-by: Jeremy Kemper jeremy@bitsweat.net

    Conflicts:

    activesupport/lib/active_support/inflector.rb
    
    

    http://github.com/rails/rails/co...

    December 15th, 2008 @ 07:05 PM

  14. Repository
    Repository

    (from [262fef7ed57520b857605a0105fe7ba9265654f6]) Make constantize look into ancestors

    [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:resolved]

    Signed-off-by: Jeremy Kemper jeremy@bitsweat.net http://github.com/rails/rails/co...

    December 15th, 2008 @ 07:05 PM

  15. Repository
    Repository

    (from [87790e00ec4a0b24146de3757d1d6892689b05e4]) Make constantize look into ancestors

    [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:resolved]

    Signed-off-by: Jeremy Kemper jeremy@bitsweat.net http://github.com/rails/rails/co...

    December 15th, 2008 @ 07:05 PM

  16. Repository
    Repository
    • State changed from resolved to open

    (from [d7b7ff0556ea5a66aeda455141ba06b558671e3d]) Revert "Make constantize look into ancestors"

    [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:open]

    This reverts commit 87790e00ec4a0b24146de3757d1d6892689b05e4. http://github.com/rails/rails/co...

    December 16th, 2008 @ 02:22 AM

  17. Repository
    Repository

    (from [981314f45cbb42d1b5403ac0d984f37c82226438]) Revert "Make constantize look into ancestors"

    [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:open]

    This reverts commit eca79e6bf052041c018c7ba08750238f8b2ecb7a. http://github.com/rails/rails/co...

    December 16th, 2008 @ 02:22 AM

  18. Repository
    Repository

    (from [19be3d35b38b6685789d8d343617d465a3652717]) Revert "Make constantize look into ancestors"

    [#410 Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9 state:open]

    This reverts commit 262fef7ed57520b857605a0105fe7ba9265654f6. http://github.com/rails/rails/co...

    December 16th, 2008 @ 02:22 AM

  19. Matt Jones
    Matt Jones
    • Milestone cleared.
    • Tag changed from activesupport, patch to activesupport, bug, patch

    What does this patch need to be accepted? It appears from some discussion here and here that the second argument to const_defined? was specifically added to make the test included here pass.

    Also ran into this in a Picnic situation; "Logger::DEBUG".constantize wasn't finding the constant.

    The 1.9 case in the current code overrides this behavior and restores the (somewhat hard to understand) behavior of Ruby 1.8. I know I was amazed when "Logger::DEBUG".constantize didn't work even though Logger::DEBUG evaluated without error.

    January 9th, 2009 @ 01:17 AM

  20. Yehuda Katz (wycats)
  21. Rohit Arondekar
    Rohit Arondekar

    Any updates in this ticket? is this still a issue on Rails master?

    June 17th, 2010 @ 07:31 AM

  22. Andrew White
    Andrew White

    The original ticket title no longer applies as eval is no longer used in constantize however Michael Johnston's failing example still fails on master.

    The actual problem now is that const_defined? doesn't look for constants in included modules in 1.8.7 but it does in 1.9.x. There's an optional second parameter that turns it off - which is what constantize does. The last patch tries to fix it by searching the ancestors list, however it's probably best to use the optimised behavior on 1.9.x and only search ancestors on 1.8.7.

    I can come up with a new patch if you want me to.

    June 17th, 2010 @ 10:50 AM

  23. Neeraj Singh
  24. Rohit Arondekar
  25. Rohit Arondekar
    Rohit Arondekar
    • Importance changed from to Low

    Andrew, have you been able to work on that patch?

    August 3rd, 2010 @ 07:50 AM

  26. Andrew White
    Andrew White

    I've looked at it and unfortunately using the optimized const_defined? in 1.9.2 returns top level constants which is different to the required behavior. I looked at using constant.constants.member? but it's unbearably slow. Therefore the technique in Fredrick's patch is about as good as it'll get and it results in about a 33% slowdown for a constant like ActiveSupport::Routing::Mapper. The same is true for 1.8.7 and 1.9.2 and const_defined? is slower by about 33% in 1.9.2 than 1.8.7 anyway.

    This may or may not be acceptable - the attached patch is basically an update of Frederick's patch.

    August 19th, 2010 @ 06:15 PM

  27. Jeremy Kemper
  28. Jeremy Kemper
  29. Santiago Pastorino
  30. Santiago Pastorino
  31. Santiago Pastorino
    Santiago Pastorino
    • Milestone changed from 3.0.5 to 3.0.6

    February 27th, 2011 @ 03:15 AM