Skip to content

Instantly share code, notes, and snippets.

@pedrocarmona
Last active September 24, 2019 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pedrocarmona/00d6980758343cbd5abae4787a7250f6 to your computer and use it in GitHub Desktop.
Save pedrocarmona/00d6980758343cbd5abae4787a7250f6 to your computer and use it in GitHub Desktop.
arel_benchmark
require 'benchmark/ips'
ActiveRecord::Base.logger = nil
def pagy_count(collection)
(c = collection.count(:all)).is_a?(Hash) ? c.size : c
end
def pagy_count2(collection)
result = collection.count(:all)
collection.group_values.empty? ? result : result.size
end
def pagy_count3(collection)
if collection.group_values.empty?
collection.count(:all)
else
collection.count(:all).size
end
end
def pagy_arel_count(collection)
# COUNT(*) OVER ()
sql = Arel.star.count.over(Arel::Nodes::Grouping.new([]))
collection.unscope(:order).limit(1).pluck(sql).first
end
def pagy_arel_conditional_count(collection)
if collection.group_values.empty?
# COUNT(*)
collection.count(:all)
else
# COUNT(*) OVER ()
sql = Arel.star.count.over(Arel::Nodes::Grouping.new([]))
collection.unscope(:order).limit(1).pluck(sql).first
end
end
collection = ::Movies::Rating.all
Benchmark.ips do |x|
x.time = 30
x.report("pagy_count:") { ApplicationRecord.uncached { pagy_count(collection) } }
x.report("pagy_count2:") { ApplicationRecord.uncached { pagy_count2(collection) } }
x.report("pagy_count3:") { ApplicationRecord.uncached { pagy_count3(collection) } }
x.report("pagy_arel_count:") { ApplicationRecord.uncached { pagy_arel_count(collection) } }
x.report("pagy_arel_conditional_count:") { ApplicationRecord.uncached { pagy_arel_conditional_count(collection) } }
x.compare!
end
<<-OUTPUT
Warming up --------------------------------------
pagy_count: 2.000 i/100ms
pagy_count2: 1.000 i/100ms
pagy_count3: 2.000 i/100ms
pagy_arel_count: 1.000 i/100ms
pagy_arel_conditional_count:
2.000 i/100ms
Calculating -------------------------------------
pagy_count: 26.297 (±19.0%) i/s - 758.000 in 30.060235s
pagy_count2: 30.137 (±26.5%) i/s - 849.000 in 30.005502s
pagy_count3: 31.145 (±16.1%) i/s - 912.000 in 30.055667s
pagy_arel_count: 7.863 (±12.7%) i/s - 227.000 in 30.119870s
pagy_arel_conditional_count:
27.263 (±22.0%) i/s - 762.000 in 30.013175s
Comparison:
pagy_count3:: 31.1 i/s
pagy_count2:: 30.1 i/s - same-ish: difference falls within error
pagy_arel_conditional_count:: 27.3 i/s - same-ish: difference falls within error
pagy_count:: 26.3 i/s - same-ish: difference falls within error
pagy_arel_count:: 7.9 i/s - 3.96x slower
OUTPUT
collection = ::Movies::Rating.group(:movie_id).select(:movie_id)
# 1682 movies
Benchmark.ips do |x|
x.time = 30
x.report("pagy_count:") { ApplicationRecord.uncached { pagy_count(collection) } }
x.report("pagy_count2:") { ApplicationRecord.uncached { pagy_count2(collection) } }
x.report("pagy_count3:") { ApplicationRecord.uncached { pagy_count3(collection) } }
x.report("pagy_arel_count:") { ApplicationRecord.uncached { pagy_arel_count(collection) } }
x.report("pagy_arel_conditional_count:") { ApplicationRecord.uncached { pagy_arel_conditional_count(collection) } }
x.compare!
end
<<-OUTPUT
Warming up --------------------------------------
pagy_count: 1.000 i/100ms
pagy_count2: 1.000 i/100ms
pagy_count3: 1.000 i/100ms
pagy_arel_count: 1.000 i/100ms
pagy_arel_conditional_count:
1.000 i/100ms
Calculating -------------------------------------
pagy_count: 5.874 (±34.0%) i/s - 166.000 in 30.288133s
pagy_count2: 9.154 (±21.8%) i/s - 256.000 in 30.024894s
pagy_count3: 9.811 (±20.4%) i/s - 278.000 in 30.101955s
pagy_arel_count: 8.969 (±33.5%) i/s - 249.000 in 30.070671s
pagy_arel_conditional_count:
12.439 (±24.1%) i/s - 351.000 in 30.087875s
Comparison:
pagy_arel_conditional_count:: 12.4 i/s
pagy_count3:: 9.8 i/s - same-ish: difference falls within error
pagy_count2:: 9.2 i/s - same-ish: difference falls within error
pagy_arel_count:: 9.0 i/s - same-ish: difference falls within error
pagy_count:: 5.9 i/s - 2.12x slower
OUTPUT
collection = ::Movies::Rating.group(:rating).select(:rating)
# 5 ratings (1,2,3,4,5)
Benchmark.ips do |x|
x.time = 30
x.report("pagy_count:") { ApplicationRecord.uncached { pagy_count(collection) } }
x.report("pagy_count2:") { ApplicationRecord.uncached { pagy_count2(collection) } }
x.report("pagy_count3:") { ApplicationRecord.uncached { pagy_count3(collection) } }
x.report("pagy_arel_count:") { ApplicationRecord.uncached { pagy_arel_count(collection) } }
x.report("pagy_arel_conditional_count:") { ApplicationRecord.uncached { pagy_arel_conditional_count(collection) } }
x.compare!
end
<<-OUTPUT
Warming up --------------------------------------
pagy_count: 1.000 i/100ms
pagy_count2: 1.000 i/100ms
pagy_count3: 1.000 i/100ms
pagy_arel_count: 1.000 i/100ms
pagy_arel_conditional_count:
1.000 i/100ms
Calculating -------------------------------------
pagy_count: 7.855 (±25.5%) i/s - 224.000 in 30.015308s
pagy_count2: 9.501 (±21.1%) i/s - 271.000 in 30.038578s
pagy_count3: 9.978 (±20.0%) i/s - 288.000 in 30.018907s
pagy_arel_count: 11.988 (±25.0%) i/s - 342.000 in 30.003528s
OUTPUT
@ddnexus
Copy link

ddnexus commented Sep 21, 2019

We missed that line 44 calls pagy_count2 instead of pagy_count3!
It should not change anything anyway :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment