Skip to content

Instantly share code, notes, and snippets.

@sandip-mane
Last active February 19, 2025 09:47
Show Gist options
  • Save sandip-mane/e4671c3cd01c247a5e8ff9133aa2eca6 to your computer and use it in GitHub Desktop.
Save sandip-mane/e4671c3cd01c247a5e8ff9133aa2eca6 to your computer and use it in GitHub Desktop.
Benchmark Rails Cache
require "benchmark"
#
# Examples:
# CacheBenchmark.new.perform
# CacheBenchmark.new(operations: 1000).perform
#
class CacheBenchmark
attr_reader :operations, :repetitions
def initialize(operations: 100_000, repetitions: 5)
# Run the benchmarks for 100k reads and writes
@operations = operations
# Run the benchmarks 5 times and take the average
@repetitions = repetitions
# Run it in the SolidCache with PG tuned setup
# SolidCache::Entry.connection.execute("SELECT pg_prewarm('solid_cache_entries')")
end
def perform
report = {}
report.merge! run_single_thread_benchmarks
report.merge! run_multi_thread_benchmarks
report
end
def run_single_thread_benchmarks
report = { "write" => [], "read" => [] }
repetitions.times do
# Clear the existing cache
Rails.cache.clear
b = Benchmark.bm(6) do |x|
x.report("write") {
operations.times { |i| cache_fetch(i) }
}
x.report("read") {
operations.times { |i| cache_fetch(i) }
}
end
b.each do |bt|
report[bt.label] << bt.real
end
end
report["write"] = report["write"].sum.fdiv(repetitions)
report["read"] = report["read"].sum.fdiv(repetitions)
{ "single_thread": report }
end
def run_multi_thread_benchmarks
report = { "write" => [], "read" => [] }
repetitions.times do
# Clear the existing cache
Rails.cache.clear
b = Benchmark.bm(6) do |x|
x.report("write") {
spawn_threads(5, operations)
}
x.report("read") {
spawn_threads(5, operations)
}
end
b.each do |bt|
report[bt.label] << bt.real
end
end
report["write"] = report["write"].sum.fdiv(repetitions)
report["read"] = report["read"].sum.fdiv(repetitions)
{ "multi_thread": report }
end
private
def cache_fetch(i)
Rails.cache.fetch(["key", i], expires_in: 5.minutes) do
"Hello World!"
end
end
# Spawn "x" threads and run "n" operations combined
def spawn_threads(x = 5, n)
threads = []
x.times do
threads << Thread.new do
(n/x).times { |i| cache_fetch(i) }
end
end
threads.each(&:join)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment