aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/examples/performance.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/examples/performance.rb')
-rw-r--r--activerecord/examples/performance.rb185
1 files changed, 185 insertions, 0 deletions
diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb
new file mode 100644
index 0000000000..1a2c78f39b
--- /dev/null
+++ b/activerecord/examples/performance.rb
@@ -0,0 +1,185 @@
+# frozen_string_literal: true
+
+require "active_record"
+require "benchmark/ips"
+
+TIME = (ENV["BENCHMARK_TIME"] || 20).to_i
+RECORDS = (ENV["BENCHMARK_RECORDS"] || TIME * 1000).to_i
+
+conn = { adapter: "sqlite3", database: ":memory:" }
+
+ActiveRecord::Base.establish_connection(conn)
+
+class User < ActiveRecord::Base
+ connection.create_table :users, force: true do |t|
+ t.string :name, :email
+ t.timestamps
+ end
+
+ has_many :exhibits
+end
+
+class Exhibit < ActiveRecord::Base
+ connection.create_table :exhibits, force: true do |t|
+ t.belongs_to :user
+ t.string :name
+ t.text :notes
+ t.timestamps
+ end
+
+ belongs_to :user
+
+ def look; attributes end
+ def feel; look; user.name end
+
+ def self.with_name
+ where("name IS NOT NULL")
+ end
+
+ def self.with_notes
+ where("notes IS NOT NULL")
+ end
+
+ def self.look(exhibits) exhibits.each(&:look) end
+ def self.feel(exhibits) exhibits.each(&:feel) end
+end
+
+def progress_bar(int); print "." if (int % 100).zero? ; end
+
+puts "Generating data..."
+
+module ActiveRecord
+ class Faker
+ LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non aliquet diam. Curabitur vel urna metus, quis malesuada elit.
+ Integer consequat tincidunt felis. Etiam non erat dolor. Vivamus imperdiet nibh sit amet diam eleifend id posuere diam malesuada. Mauris at accumsan sem.
+ Donec id lorem neque. Fusce erat lorem, ornare eu congue vitae, malesuada quis neque. Maecenas vel urna a velit pretium fermentum. Donec tortor enim,
+ tempor venenatis egestas a, tempor sed ipsum. Ut arcu justo, faucibus non imperdiet ac, interdum at diam. Pellentesque ipsum enim, venenatis ut iaculis vitae,
+ varius vitae sem. Sed rutrum quam ac elit euismod bibendum. Donec ultricies ultricies magna, at lacinia libero mollis aliquam. Sed ac arcu in tortor elementum
+ tincidunt vel interdum sem. Curabitur eget erat arcu. Praesent eget eros leo. Nam magna enim, sollicitudin vehicula scelerisque in, vulputate ut libero.
+ Praesent varius tincidunt commodo".split
+
+ def self.name
+ LOREM.grep(/^\w*$/).sort_by { rand }.first(2).join " "
+ end
+
+ def self.email
+ LOREM.grep(/^\w*$/).sort_by { rand }.first(2).join("@") + ".com"
+ end
+ end
+end
+
+# pre-compute the insert statements and fake data compilation,
+# so the benchmarks below show the actual runtime for the execute
+# method, minus the setup steps
+
+# Using the same paragraph for all exhibits because it is very slow
+# to generate unique paragraphs for all exhibits.
+notes = ActiveRecord::Faker::LOREM.join " "
+today = Date.today
+
+puts "Inserting #{RECORDS} users and exhibits..."
+RECORDS.times do |record|
+ user = User.create(
+ created_at: today,
+ name: ActiveRecord::Faker.name,
+ email: ActiveRecord::Faker.email
+ )
+
+ Exhibit.create(
+ created_at: today,
+ name: ActiveRecord::Faker.name,
+ user: user,
+ notes: notes
+ )
+ progress_bar(record)
+end
+puts "Done!\n"
+
+Benchmark.ips(TIME) do |x|
+ ar_obj = Exhibit.find(1)
+ attrs = { name: "sam" }
+ attrs_first = { name: "sam" }
+ attrs_second = { name: "tom" }
+ exhibit = {
+ name: ActiveRecord::Faker.name,
+ notes: notes,
+ created_at: Date.today
+ }
+
+ x.report("Model#id") do
+ ar_obj.id
+ end
+
+ x.report "Model.new (instantiation)" do
+ Exhibit.new
+ end
+
+ x.report "Model.new (setting attributes)" do
+ Exhibit.new(attrs)
+ end
+
+ x.report "Model.first" do
+ Exhibit.first.look
+ end
+
+ x.report "Model.take" do
+ Exhibit.take
+ end
+
+ x.report("Model.all limit(100)") do
+ Exhibit.look Exhibit.limit(100)
+ end
+
+ x.report("Model.all take(100)") do
+ Exhibit.look Exhibit.take(100)
+ end
+
+ x.report "Model.all limit(100) with relationship" do
+ Exhibit.feel Exhibit.limit(100).includes(:user)
+ end
+
+ x.report "Model.all limit(10,000)" do
+ Exhibit.look Exhibit.limit(10000)
+ end
+
+ x.report "Model.named_scope" do
+ Exhibit.limit(10).with_name.with_notes
+ end
+
+ x.report "Model.create" do
+ Exhibit.create(exhibit)
+ end
+
+ x.report "Resource#attributes=" do
+ e = Exhibit.new(attrs_first)
+ e.attributes = attrs_second
+ end
+
+ x.report "Resource#update" do
+ Exhibit.first.update(name: "bob")
+ end
+
+ x.report "Resource#destroy" do
+ Exhibit.first.destroy
+ end
+
+ x.report "Model.transaction" do
+ Exhibit.transaction { Exhibit.new }
+ end
+
+ x.report "Model.find(id)" do
+ User.find(1)
+ end
+
+ x.report "Model.find_by_sql" do
+ Exhibit.find_by_sql("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}").first
+ end
+
+ x.report "Model.log" do
+ Exhibit.connection.send(:log, "hello", "world") {}
+ end
+
+ x.report "AR.execute(query)" do
+ ActiveRecord::Base.connection.execute("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}")
+ end
+end