Skip to content

Commit

Permalink
Add benchmark for many collectors
Browse files Browse the repository at this point in the history
  • Loading branch information
adamlogic committed Dec 5, 2023
1 parent bcf5cc8 commit 8d20ac8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
13 changes: 13 additions & 0 deletions judoscale-sidekiq/lib/judoscale/sidekiq/metrics_collector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
module Judoscale
module Sidekiq
class MetricsCollector < Judoscale::JobMetricsCollector
RECENT = 1 # second
RECENT_KEY = "judoscale:sidekiq:recent"
RECENT_VALUE = "1"

def self.adapter_config
Judoscale::Config.instance.sidekiq
end

def collect
return [] if collected_recently?

metrics = []
queues_by_name = ::Sidekiq::Queue.all.each_with_object({}) do |queue, obj|
obj[queue.name] = queue
Expand Down Expand Up @@ -45,6 +51,13 @@ def collect
log_collection(metrics)
metrics
end

private

def collected_recently?
# If another process has collected metrics recently, we don't need to.
!::Sidekiq.redis { |r| r.set RECENT_KEY, RECENT_VALUE, nx: true, ex: RECENT }
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
require "minitest/benchmark"
require "judoscale/sidekiq/metrics_collector"

class CollectBenchmark < Minitest::Benchmark
class CollectWithLargeQueuesBenchmark < Minitest::Benchmark
BATCH_SIZE = 1_000
MAX_RETRIES = 3

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

require "test_helper"
require "minitest/benchmark"
require "judoscale/sidekiq/metrics_collector"

class CollectWithManyReportersBenchmark < Minitest::Benchmark
BATCH_SIZE = 1_000
QUEUES = %w[one two three four five six seven eight nine ten]

# performance assertions will iterate over `bench_range`.
# We'll use it to define the number Collector instances running.
def self.bench_range
[1, 100]
end

def setup
@collectors = {}
sidekiq_args = BATCH_SIZE.times.map { [] }

# Enqueue jobs on several queues
QUEUES.each do |queue|
Sidekiq::Client.push_bulk "class" => "Foo", "args" => sidekiq_args, "queue" => queue
end

self.class.bench_range.each do |n|
@collectors[n] = n.times.map { Judoscale::Sidekiq::MetricsCollector.new }
end

# Run a collection to prime the cache (what cache?)
Judoscale::Sidekiq::MetricsCollector.new.collect
end

def bench_collect
validation = proc do |range, times|
# 100 collectors should take way less than 100x the time of 1 collector.
# The 50x factor is arbitrary, but it's a good indicator that we're short-circuiting
# the collection process for redundant collectors.
assert_operator times.last, :<, times.first * 50
end

assert_performance validation do |n|
@collectors.fetch(n).each do |collector|
collector.collect
end
end
end
end

0 comments on commit 8d20ac8

Please sign in to comment.