I''ve been experiencing a performance issue using Edge and it appears to be related to how Dependencies handles classes that are generated at runtime. I''ll give a simplified scenario of my problem for the sake of clarity. These are the migrations: 001_create_publications.rb: class CreatePublications < ActiveRecord::Migration def self.up create_table :publications do |t| t.column :name, :string t.column :type, :string end end def self.down drop_table :publications end end These are the current values in the table: 1, ''A Tale of Two Cities'', ''Book'' 2, ''1984'', ''Book'' And the models... app/models/publication.rb: class Publication < ActiveRecord::Base end Now, Book would be a model that is generated at runtime (i.e., it is not found in a file). While it wouldn''t necessarily make sense for this sort of setup, it does in a plugin like acts_as_versioned that generates a, for example, Publication::Version class at runtime. So this is what I''m running in the console: Loading development environment.>> Object.const_set(''Book'', Class.new(Publication))=> Book>> Book.find(:all)=> [#<Book:0x5966dd8 @attributes={"name"=>"A Tale of Two Cities", "type"=>"Book", "id"=>"1"}>, #<Book:0x5965898 @attributes={"name"=>"A Tale of Three Cities", "type"=>"Book", "id"=>"2"}>]>> Book.find(:all)=> [#<Book:0x5961ff4 @attributes={"name"=>"A Tale of Two Cities", "type"=>"Book", "id"=>"1"}>, #<Book:0x5960ab4 @attributes={"name"=>"A Tale of Three Cities", "type"=>"Book", "id"=>"2"}>] This produces the right results, however a log from the dependencies shows the following: Book Columns (0.000000) SHOW FIELDS FROM publications Book Load (0.016000) SELECT * FROM publications WHERE ( (publications.`type` = ''Book'' ) ) Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", []) Dependencies: called new_constants_in() Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", []) Dependencies: called new_constants_in() Book Load (0.016000) SELECT * FROM publications WHERE ( (publications.`type` = ''Book'' ) ) Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", []) Dependencies: called new_constants_in() Dependencies: called require_or_load("/book", nil) Dependencies: loading /book Dependencies: called load_file("/book.rb", []) Dependencies: called new_constants_in() As a result of how things are currently working, it appears as though it will try to look for a book file every single time an instance of Book is instantiated, regardless of whether it''s looked for it before. This seems to be what is causing my performance issue. My question is: Is this behavior expected? That is, should ActiveRecord classes that are generated at runtime be causing Dependencies to constantly look for the file? A first crack at the issue shows that require_association_class in associations.rb is calling require_association, which in turn will cause the Dependencies to look for a file named ''book''. This is regardless of whether the constant already exists. I''m tempted to add a conditional that only calls require_association if the constant does not already exist (or even going deeper and having associate_with check if the constant exists). However, I haven''t yet looked into the issues this could cause with other parts of ActiveRecord. Thanks to anyone who might have insight into the issue. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Maybe this is too simple an answer, but have you checked what environment the console is running in? The startup message indicates that it''s in development, where automatic reloading of classes is a feature, not a bug.. -- Matt Jones mdj.acme@gmail.com President/Technical Director, Acme Art Company (acmeartco.org) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Indeed, I am running in development ;) However, this is run from the console and automatic reloading only occurs when the server is reset (i.e. on page load). In this case, Rails is trying to load the (nonexistent) file every single time the class is instantiated. So, when I have 150 Book records instantiated in Development, Rails will try looking through the $LOAD_PATH for book.rb every time an instance of Book is created (even though the constant already exists). Granted, after the server is reset, I would expect Rails to reload the Book constant, but only once not 150 times :( This is the change I''ve made to currently resolve the problem: Index: activerecord/lib/active_record/associations.rb ==================================================================--- activerecord/lib/active_record/associations.rb (revision 5478) +++ activerecord/lib/active_record/associations.rb (working copy) @@ -948,7 +948,7 @@ end def require_association_class(class_name) - require_association(Inflector.underscore(class_name)) if class_name + require_association(Inflector.underscore(class_name)) if class_name && !Dependencies.qualified_const_defined?(class_name) end def add_multiple_associated_save_callbacks(association_name) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Matt Jones wrote:> Maybe this is too simple an answer, but have you checked what environment > the > console is running in? The startup message indicates that it''s in > development, > where automatic reloading of classes is a feature, not a bug..Well I thought I''d try it in production just to see what would happen, but still having the same problem: Book Columns (0.000000) SHOW FIELDS FROM publications Book Load (0.015000) SELECT * FROM publications WHERE ( (publications.`type` = ''Book'' ) ) Dependencies: called require_or_load("book", nil) Dependencies: requiring book Dependencies: called new_constants_in(Object) Dependencies: New constants: Dependencies: Error during loading, removing partially loaded constants Dependencies: called require_or_load("book", nil) Dependencies: called clear() Book Load (0.000000) SELECT * FROM publications WHERE ( (publications.`type` = ''Book'' ) ) Dependencies: called require_or_load("book", nil) Dependencies: requiring book Dependencies: called new_constants_in(Object) Dependencies: New constants: Dependencies: Error during loading, removing partially loaded constants Dependencies: called require_or_load("book", nil) You''ll notice that it attempts to load the file again after a reload (see ...called clear()). Now the error I''m getting is the fault of require_association. Since this is always called when an ActiveRecord class instantiated, it will cause the following error: no such file to load -- book ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:492 :in `require'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:492 :in `require'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:337 :in `new_constants_in'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:492 :in `require'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:105 :in `require_or_load'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:61: in `depend_on'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:67: in `associate_with'' ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:440 :in `require_association'' ... Note though that you''ll never see that exception because Dependencies.new_constants_in eats it up. Again, the patch I posted before fixes the problem, but I''m not certain this is the real root of the problem. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---