Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require "bundler/inline"
- gemfile(true) do
- ruby "2.3.4"
- source "https://rubygems.org"
- gem "activerecord", "5.0.0"
- gem "minitest", "5.9.0"
- gem "paper_trail", path: "..", require: false
- gem "sqlite3"
- gem "mysql2"
- gem "pg"
- end
- require "active_record"
- require "minitest/autorun"
- require "logger"
- require "benchmark"
- ActiveRecord::Base.establish_connection(
- :adapter => "mysql2",
- :host => "localhost",
- :username => "",
- :password => "",
- :database => "benchmark")
- #adapter: "sqlite3", database: "benchmark.sqlite")
- '''
- :adapter => "postgresql",
- :host => "localhost",
- :username => "postgres",
- :password => "",
- :database => "benchmark"
- )'''
- # #. database: ":memory:")
- ActiveRecord::Base.logger = nil
- begin
- # we generate a large dataset, but we only read from it... so just take the last if there is any and don't throw an error
- ActiveRecord::Schema.define do
- create_table :physicians do |t|
- t.string :name
- t.timestamps
- end
- create_table :patients do |t|
- t.string :name
- t.timestamps
- end
- create_table :appointments do |t|
- t.belongs_to :physician, index: true
- t.belongs_to :patient, index: true
- t.datetime :appointment_date
- t.timestamps
- end
- create_table :versions do |t|
- t.string :item_type, null: false
- t.integer :item_id, null: false
- t.string :event, null: false
- t.string :whodunnit
- t.text :object, limit: 1_073_741_823
- t.text :object_changes, limit: 1_073_741_823
- t.integer :transaction_id
- t.datetime :created_at
- end
- add_index :versions, %i[item_type item_id]
- add_index :versions, [:transaction_id]
- create_table :version_associations do |t|
- t.integer :version_id
- t.string :foreign_key_name, null: false
- t.integer :foreign_key_id
- end
- add_index :version_associations, [:version_id]
- add_index :version_associations, %i[foreign_key_name foreign_key_id],
- name: "index_version_associations_on_foreign_key"
- end
- rescue
- end
- #ActiveRecord::Base.logger = Logger.new(STDOUT)
- require "paper_trail/config"
- PaperTrail::Config.instance.track_associations = true
- require "paper_trail"
- class Physician < ActiveRecord::Base
- has_many :appointments
- has_many :patients, through: :appointments
- has_paper_trail on: [:update]
- end
- class Appointment < ActiveRecord::Base
- belongs_to :physician
- belongs_to :patient
- has_paper_trail on: [:update]
- end
- class Patient < ActiveRecord::Base
- has_many :appointments
- has_many :physicians, through: :appointments
- has_paper_trail on: [:update]
- end
- class PerformanceTest < ActiveSupport::TestCase
- setup do
- if PaperTrail::Version.count == 0
- physicians = 10
- patients = 10_000
- appointments = 10_000
- changes_per_transaction = 10
- transactions = 10_000
- puts "Generating Dataset"
- start = Time.now
- ActiveRecord::Base.transaction { generate_physicians(physicians) }
- puts "Generated Physicians:", Physician.count, Time.now - start
- start = Time.now
- ActiveRecord::Base.transaction { generate_patients(patients) }
- puts "Generated Patients:", Patient.count, Time.now - start
- start = Time.now
- ActiveRecord::Base.transaction { generate_appointments(appointments) }
- puts "Generated Appointments: ", Appointment.count, Time.now - start
- start = Time.now
- (0..transactions).each do |seed|
- ActiveRecord::Base.transaction { change_stuff(seed, changes_per_transaction) }
- puts "Changed Stuff (#{seed}): #{Time.now - start} "
- start = Time.now
- end
- end
- end
- def check_performance_many(version)
- Benchmark.realtime { PaperTrail::Reifier::reify(version, has_many: true) }
- end
- def check_performance_many_through(version)
- Benchmark.realtime { PaperTrail::Reifier::reify(version, has_many_through: true) }
- end
- def check_performance(seed, type_name)
- rnd = Random.new(seed)
- number = 30
- has_many = 0
- has_many_through = 0
- number.times do
- offset = rnd.rand(PaperTrail::Version.where(item_type: type_name).count)
- version = PaperTrail::Version.where(item_type: type_name).offset(offset).first
- has_many += check_performance_many(version)
- has_many_through += check_performance_many_through(version)
- end
- puts "#{type_name} has_many: #{has_many / number} has_many_through: #{has_many_through}"
- end
- def generate_physicians(amount)
- count = Physician.count
- (count...amount).each do |index|
- real_index = index
- Physician.new(name: "Physician #{real_index}").save(validate: false)
- end
- end
- def generate_patients(amount)
- count = Patient.count
- (count...amount).each do |index|
- real_index = index
- Patient.new(name: "Patient #{real_index}").save(validate: false)
- end
- end
- def generate_appointments(relations)
- date = Date.new(2018, 1, 1)
- patients = Patient.count
- physicians = Physician.count
- count = Appointment.count
- rnd = Random.new(0)
- (count...relations).each do |index|
- patient_id = rnd.rand(patients) + 1
- physician_id = rnd.rand(physicians) + 1
- Appointment.new(appointment_date: date, patient_id: patient_id, physician_id: physician_id).save(validate: false)
- end
- end
- def change_stuff(seed, changes)
- patients = Patient.count
- physicians = Physician.count
- appointments = Appointment.count
- rnd = Random.new(seed)
- date = Date.new(2018, 1, 1)
- (0..changes).each do |index|
- appointment = rnd.rand(appointments) + 1
- day = rnd.rand(1000)
- Appointment.find(appointment).update(appointment_date: date + day)
- patient = rnd.rand(patients) + 1
- name = rnd.rand
- Patient.find(patient).update(name: "Patient #{patient} #{name}")
- physician = rnd.rand(physicians) + 1
- name = rnd.rand
- Physician.find(physician).update(name: "Physician #{physician} #{name}")
- end
- end
- def test_has_many
- #ActiveRecord::Base.logger = Logger.new(STDOUT)
- check_performance(0, 'Patient')
- check_performance(0, 'Physician')
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement