Number of iterations per second
Allocated objects
Active record/postgres discourse Script
View on Github
require 'bundler/setup'
require 'active_record'
require_relative 'support/benchmark_rails'
db_setup script: "bm_discourse_setup.rb"
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
class User < ActiveRecord::Base
has_many :topic_users
has_many :category_users
has_many :topics
end
class Topic < ActiveRecord::Base
has_many :topic_users
has_many :categories
belongs_to :user
belongs_to :category
scope :listable_topics, -> { where('topics.archetype <> ?', 'private_message') }
end
class TopicUser < ActiveRecord::Base
belongs_to :topic
belongs_to :user
end
class Category < ActiveRecord::Base
has_many :category_users
has_many :topics
belongs_to :topic
end
class CategoryUser < ActiveRecord::Base
belongs_to :category
belongs_to :user
end
user = User.first
Benchmark.rails("active_record/#{db_adapter}_discourse", time: 5) do
str = ""
Topic
.unscoped
.preload(:user)
.includes(:category)
.references(:category)
.joins("LEFT OUTER JOIN topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{user.id})")
.listable_topics
.where('COALESCE(categories.topic_id, 0) <> topics.id')
.where('topics.deleted_at IS NULL')
.where(
"NOT EXISTS (
SELECT 1 FROM category_users cu
WHERE cu.user_id = :user_id
AND cu.category_id = topics.category_id
AND cu.notification_level = :muted
AND cu.category_id <> :category_id
AND (tu.notification_level IS NULL OR tu.notification_level < :tracking)
)",
user_id: user.id, muted: 0, tracking: 2, category_id: -1
).where("pinned_globally AND pinned_at IS NOT NULL AND (topics.pinned_at > tu.cleared_pinned_at OR tu.cleared_pinned_at IS NULL)")
.order("topics.bumped_at DESC")
.limit(30)
.each do |topic|
str << "id: #{topic.id} title: #{topic.title} created_at: #{topic.created_at.iso8601} user: #{topic.user.username}\n"
end
end
Sequel/postgres discourse Script
View on Github
require "bundler/setup"
require "sequel"
require_relative "support/benchmark_sequel"
db_setup script: "bm_discourse_setup.rb"
DB = Sequel.connect(ENV.fetch("DATABASE_URL"))
class User < Sequel::Model
one_to_many :topic_users
one_to_many :category_users
one_to_many :topics
end
class Topic < Sequel::Model
one_to_many :topic_users
one_to_many :categories
many_to_one :user
many_to_one :category
dataset_module do
def listable_topics
where(Sequel.lit("topics.archetype <> ?", "private_message"))
end
end
end
class TopicUser < Sequel::Model
many_to_one :topic
many_to_one :user
end
class Category < Sequel::Model
one_to_many :category_users
one_to_many :topics
many_to_one :topic
end
class CategoryUser < Sequel::Model
many_to_one :category
many_to_one :user
end
user = User.first
Benchmark.sequel("sequel/#{db_adapter}_discourse", time: 5) do
str = ""
Topic
.unfiltered
.eager_graph(Sequel.as(:category, :categories))
.eager(:user)
.left_outer_join(Sequel.lit("topic_users AS tu ON (topics.id = tu.topic_id AND tu.user_id = #{user.id})"))
.listable_topics
.where(Sequel.lit("COALESCE(categories.topic_id, 0) <> topics.id"))
.where(Sequel.lit("topics.deleted_at IS NULL"))
.where(Sequel.lit(
"NOT EXISTS (
SELECT 1 FROM category_users cu
WHERE cu.user_id = :user_id
AND cu.category_id = topics.category_id
AND cu.notification_level = :muted
AND cu.category_id <> :category_id
AND (tu.notification_level IS NULL OR tu.notification_level < :tracking)
)",
user_id: user.id, muted: 0, tracking: 2, category_id: -1)
).where(
Sequel.lit(
"pinned_globally AND
pinned_at IS NOT NULL AND
(topics.pinned_at > tu.cleared_pinned_at OR tu.cleared_pinned_at IS NULL)"
)
).order(Sequel.lit("topics.bumped_at DESC"))
.limit(30)
.all
.each do |topic|
str << "id: #{topic.id} title: #{topic.title} created_at: #{topic.created_at.iso8601} user: #{topic.user.username}\n"
end
end