-
Aaron Patterson authored
We're trying to make instantiating models cheaper (for example doing `Post.new`), and discovered in the course of profiling that `respond_to?` is responsible for some amount of initialization allocations. This patch changes `Model.respond_to?` to not allocate anymore which should help initialization performance (as well as other queries). Here is the benchmark we used: ```ruby require "active_record" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Schema.define do create_table :posts, force: true do |t| t.string :title, default: "hello" t.text :body, default: "i am a blog post" t.string :author, default: "aaron" t.boolean :published, default: true t.integer :likes, default: 1000000 end end class Post < ActiveRecord::Base end 5.times { Post.new } def m x = GC.stat(:total_allocated_objects) yield GC.stat(:total_allocated_objects) - x end allocs = m { 5000.times { Post.new } } p ALLOCATIONS_PER_MODEL: (allocs / 5000) allocs = m { 5000.times { Post.respond_to?(:default_scope) } } p ALLOCATIONS_PER_RESPOND_TO: (allocs / 5000) ``` Before this patch: ``` $ bundle exec ruby -Iactiverecord/lib:~/git/vernier/lib test.rb -- create_table(:posts, {force: true}) -> 0.0045s {ALLOCATIONS_PER_MODEL: 9} {ALLOCATIONS_PER_RESPOND_TO: 2} ``` After this patch: ``` $ bundle exec ruby -Iactiverecord/lib:~/git/vernier/lib test.rb -- create_table(:posts, {force: true}) -> 0.0045s {ALLOCATIONS_PER_MODEL: 7} {ALLOCATIONS_PER_RESPOND_TO: 0} ``` Co-Authored-By:
Eileen M. Uchitelle <eileencodes@gmail.com>
Aaron Patterson authoredWe're trying to make instantiating models cheaper (for example doing `Post.new`), and discovered in the course of profiling that `respond_to?` is responsible for some amount of initialization allocations. This patch changes `Model.respond_to?` to not allocate anymore which should help initialization performance (as well as other queries). Here is the benchmark we used: ```ruby require "active_record" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Schema.define do create_table :posts, force: true do |t| t.string :title, default: "hello" t.text :body, default: "i am a blog post" t.string :author, default: "aaron" t.boolean :published, default: true t.integer :likes, default: 1000000 end end class Post < ActiveRecord::Base end 5.times { Post.new } def m x = GC.stat(:total_allocated_objects) yield GC.stat(:total_allocated_objects) - x end allocs = m { 5000.times { Post.new } } p ALLOCATIONS_PER_MODEL: (allocs / 5000) allocs = m { 5000.times { Post.respond_to?(:default_scope) } } p ALLOCATIONS_PER_RESPOND_TO: (allocs / 5000) ``` Before this patch: ``` $ bundle exec ruby -Iactiverecord/lib:~/git/vernier/lib test.rb -- create_table(:posts, {force: true}) -> 0.0045s {ALLOCATIONS_PER_MODEL: 9} {ALLOCATIONS_PER_RESPOND_TO: 2} ``` After this patch: ``` $ bundle exec ruby -Iactiverecord/lib:~/git/vernier/lib test.rb -- create_table(:posts, {force: true}) -> 0.0045s {ALLOCATIONS_PER_MODEL: 7} {ALLOCATIONS_PER_RESPOND_TO: 0} ``` Co-Authored-By:
Eileen M. Uchitelle <eileencodes@gmail.com>
Loading