Skip to content

Instantly share code, notes, and snippets.

@maxjustus
Last active November 10, 2015 19:50
Show Gist options
  • Save maxjustus/376ae06d09f4a88a38d3 to your computer and use it in GitHub Desktop.
Save maxjustus/376ae06d09f4a88a38d3 to your computer and use it in GitHub Desktop.
Benchmark for db locking approaches
require 'benchmark/ips'
carts = 10.times.map { Cart.create! account: Account.first }
carts.each { |cart|
items = Account.first.product_options.sample(5)
items.each { |item| cart.line_items.create product_option_id: item.id, quantity: 1 }
}
def all_at_once(carts, &blk)
pids = carts.map do |cart|
fork do
ActiveRecord::Base.connection.reconnect!
variable = ConditionVariable.new
mutex = Mutex.new
Signal.trap("USR1") do
variable.broadcast
end
thread = Thread.new do
mutex.synchronize {
variable.wait(mutex)
Cart.transaction do
begin
blk.call(cart)
sleep 2
rescue => e
puts e
puts "Retrying"
retry
end
end
}
end
loop do
sleep 0.1
break if thread.status != "sleep"
end
thread.join
end
end
sleep 1
puts "cue the herd"
pids.each { |pid| Process.kill("USR1", pid) }
Process.waitall
end
def iterative(carts)
all_at_once(carts) do |cart|
cart.line_items.each { |item| item.product_option.lock! }
end
end
def one_shot(carts)
all_at_once(carts) do |cart|
ProductOption.where(id: cart.line_items.map(&:product_option_id)).lock!.count
end
end
Benchmark.ips do |x|
x.report "iterative locking" do
iterative(carts)
end
x.report "one shot locking" do
one_shot(carts)
end
end
carts.each(&:destroy)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment