Skip to content

Instantly share code, notes, and snippets.

@etaque
Created November 26, 2012 06:10
Show Gist options
  • Save etaque/4146802 to your computer and use it in GitHub Desktop.
Save etaque/4146802 to your computer and use it in GitHub Desktop.
Benchmark MongoDB#$inc vs Redis#hincrbyfloat
source :rubygems
gem 'redis'
gem 'mongoid'
gem 'celluloid'
production:
sessions:
default:
database: benchmark_gauges
hosts:
- localhost:27017
require 'rubygems'
require 'bundler'
Bundler.require
account_refs = (0..1000).map{|i| "%010d" % i}
usages = (0..9).map{|i| "usage#{i}" }
month = "2012-12"
ENV['MONGOID_ENV'] = 'production'
Mongoid.load!("mongoid.yml")
class Gauge
include Mongoid::Document
field :account_ref, type: String
field :month, type: String
field :values, type: Hash
index({account_ref: 1, month: 1})
end
Gauge.create_indexes
class Worker
include Celluloid
def initialize(count)
@count = count
@account_refs = (0..100).map{|i| "%010d" % i}
@usages = (0..9).map{|i| "usage#{i}" }
@month = "2012-12"
end
end
class RedisWorker < Worker
def work
redis = Redis.new
@count.times do
key = ["fairuse", @account_refs.sample, @month].join(":")
redis.hincrbyfloat(key, @usages.sample, rand.round(5))
end
true
end
end
class MongoDBWorker < Worker
def work
@count.times do
Gauge.where({account_ref: @account_refs.sample, month: @month}).
find_and_modify({"values" => { "usage" => {"$inc" => rand.round(5) } } },
new: true, upsert: true)
end
true
end
end
class Runner
def initialize(pool_size, count)
@count = count
@pool_size = pool_size
@redis_pool = RedisWorker.pool(size: pool_size, args: [count])
@mongodb_pool = MongoDBWorker.pool(size: pool_size, args: [count])
@redis_times = []
@mongodb_times = []
end
def run
t = Time.now
@pool_size.times.map { @redis_pool.future :work }.map(&:value)
@redis_times << Time.now - t
t = Time.now
@pool_size.times.map { @mongodb_pool.future :work }.map(&:value)
@mongodb_times << Time.now - t
end
def print
puts "Redis: #{@redis_times.sum / @redis_times.size}"
puts "MongoDB: #{@mongodb_times.sum / @mongodb_times.size}"
end
end
pool_size, count = *ARGV
@runner = Runner.new(pool_size.to_i, count.to_i)
5.times do |i|
puts "Iteration #{i}"
@runner.run
end
@runner.print
@etaque
Copy link
Author

etaque commented Nov 26, 2012

emilien:ruby-1.9.3 gauges/ $ ruby run.rb 4 1000
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Redis: 0.6949892
MongoDB: 2.9080958

emilien:ruby-1.9.3 gauges/ $ ruby run.rb 10 1000
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Redis: 1.5602584
MongoDB: 6.273723800000001

@etaque
Copy link
Author

etaque commented Nov 26, 2012

emilien:ruby-1.9.3 gauges/ $ ruby run.rb 10 10000
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Redis: 19.4338594
MongoDB: 78.7857702

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