This project is archived and is in readonly mode.
Inflector.constantize uses eval which is slow in JRuby and Ruby 1.9
-
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.
-
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...
-
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...
-
Jeremy Kemper
- Assigned user set to Jeremy Kemper
- Tag changed from patch to activesupport, patch
- Milestone set to 2.1.1
-
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}") endend end
Bob::Mary.doit
for an example in the wild see the init function of picnic -
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.doitfor an example in the wild see the init function of picnic
-
Michael Johnston
actually, this fails too:
class Outer2 module Why TOM2 = 5 end include Why end "Outer2::TOM2".constantizewhich is why "Logger::INFO".constantize fails which is (another reason) why picnic fails.
-
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?
-
Jeremy Kemper
- Milestone changed from 2.1.1 to 2.1.3
-
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.
-
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
-
Frederick Cheung
Oops, ruby 1.9 changes were a bit off. This should be better
-
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 -
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...
-
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...
-
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...
-
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...
-
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...
-
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.
-
Yehuda Katz (wycats)
- Milestone cleared.
-
Rohit Arondekar
Any updates in this ticket? is this still a issue on Rails master?
-
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.
-
Neeraj Singh
+1 for Andrew's idea.
-
Rohit Arondekar
+1 from me too
-
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.
