Created
April 4, 2017 01:49
-
-
Save kevingriffin/29d7e4774d210a41116c063dfd430de0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Results: | |
## CollectionProxies (1000000): 30.980000 2.890000 33.870000 ( 33.993120) | |
## Associations (1000000): 0.120000 0.000000 0.120000 ( 0.120288) | |
require 'active_record' | |
require 'sqlite3' | |
require 'benchmark' | |
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:" | |
ActiveRecord::Schema.define do | |
create_table(:as) do |t| | |
end | |
create_table(:bs) do |t| | |
t.references :a | |
end | |
create_table(:cs) do |t| | |
t.references :b | |
end | |
create_table(:ds) do |t| | |
t.references :c | |
end | |
end | |
class A < ActiveRecord::Base | |
has_many :bs, inverse_of: :a, dependent: :destroy | |
end | |
class B < ActiveRecord::Base | |
belongs_to :a, inverse_of: :bs | |
has_many :cs, inverse_of: :b, dependent: :destroy | |
end | |
class C < ActiveRecord::Base | |
belongs_to :b, inverse_of: :cs | |
has_many :ds, inverse_of: :c, dependent: :destroy | |
end | |
class D < ActiveRecord::Base | |
belongs_to :c, inverse_of: :ds | |
end | |
# Make a tree of a million records and iterate it. | |
ActiveRecord::Base.connection.execute("create temporary table ten (integer)") | |
ActiveRecord::Base.connection.execute("insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)") | |
ActiveRecord::Base.connection.execute("insert into \"as\" select null from ten join ten") | |
ActiveRecord::Base.connection.execute("insert into \"bs\" (a_id) select id from \"as\" join ten join ten") | |
ActiveRecord::Base.connection.execute("insert into \"cs\" (b_id) select id from \"bs\" join ten") | |
ActiveRecord::Base.connection.execute("insert into \"ds\" (c_id) select id from \"cs\" join ten") | |
def traverse_collection_proxies(as) | |
count = 0 | |
as.each do |a| | |
a.bs.each do |b| | |
b.cs.each do |c| | |
c.ds.each do | |
count += 1 | |
end | |
end | |
end | |
end | |
count | |
end | |
def traverse_associations(as) | |
count = 0 | |
as.each do |a| | |
a.association(:bs).target.each do |b| | |
b.association(:cs).target.each do |c| | |
c.association(:ds).target.each do | |
count += 1 | |
end | |
end | |
end | |
end | |
count | |
end | |
def without_gc | |
GC.start | |
GC.disable | |
yield | |
GC.enable | |
end | |
loaded = A.includes(:bs => { :cs => :ds }).to_a | |
without_gc do | |
count = nil | |
bm = Benchmark.measure { count = traverse_collection_proxies(loaded) } | |
puts "CollectionProxies (#{count}): #{bm}" | |
end | |
loaded = A.includes(:bs => { :cs => :ds }).to_a | |
without_gc do | |
count = nil | |
bm = Benchmark.measure { count = traverse_associations(loaded) } | |
puts "Associations (#{count}): #{bm}" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment