Add pool_concurrency_test manual spec

Add MT connection count without Mutex
This commit is contained in:
Brian J. Cardiff 2023-11-30 11:26:02 -03:00
parent 06df272740
commit 684b8ac032
2 changed files with 104 additions and 5 deletions

View file

@ -1,4 +1,3 @@
require "spec"
require "../src/db"
class DummyDriver < DB::Driver
@ -17,20 +16,37 @@ class DummyDriver < DB::Driver
end
class DummyConnection < DB::Connection
@@connections = [] of DummyConnection
@@connections_count = Atomic(Int32).new(0)
def initialize(options : DB::Connection::Options)
super(options)
Fiber.yield
@@connections_count.add(1)
@connected = true
@@connections ||= [] of DummyConnection
@@connections.not_nil! << self
{% unless flag?(:preview_mt) %}
# @@connections is only used in single-threaded mode in specs
# for benchmarks we want to avoid the overhead of synchronizing this array
@@connections << self
{% end %}
end
def self.connections_count
@@connections_count.get
end
def self.connections
@@connections.not_nil!
{% if flag?(:preview_mt) %}
raise "DummyConnection.connections is only available in single-threaded mode"
{% end %}
@@connections
end
def self.clear_connections
@@connections.try &.clear
{% if flag?(:preview_mt) %}
raise "DummyConnection.clear_connections is only available in single-threaded mode"
{% end %}
@@connections.clear
end
def build_prepared_statement(query) : DB::Statement
@ -117,17 +133,30 @@ class DummyDriver < DB::Driver
end
class DummyStatement < DB::Statement
@@statements_count = Atomic(Int32).new(0)
@@statements_exec_count = Atomic(Int32).new(0)
property params
def initialize(connection, command : String, @prepared : Bool)
@params = Hash(Int32 | String, DB::Any | Array(DB::Any)).new
super(connection, command)
@@statements_count.add(1)
raise DB::Error.new(command) if command == "syntax error"
end
def self.statements_count
@@statements_count.get
end
def self.statements_exec_count
@@statements_exec_count.get
end
protected def perform_query(args : Enumerable) : DB::ResultSet
assert_not_closed!
@@statements_exec_count.add(1)
Fiber.yield
@connection.as(DummyConnection).check
set_params args
@ -137,6 +166,8 @@ class DummyDriver < DB::Driver
protected def perform_exec(args : Enumerable) : DB::ExecResult
assert_not_closed!
@@statements_exec_count.add(1)
@connection.as(DummyConnection).check
set_params args
raise DB::Error.new("forced exception due to query") if command == "raise"

View file

@ -0,0 +1,68 @@
# This file is to be executed as:
#
# % crystal run --release [-Dpreview_mt] ./spec/manual/pool_concurrency_test.cr -- --options="max_pool_size=5" --duration=30 --concurrency=4
#
#
require "option_parser"
require "../dummy_driver"
require "../../src/db"
options = ""
duration = 3
concurrency = 4
OptionParser.parse do |parser|
parser.banner = "Usage: pool_concurrency_test [arguments]"
parser.on("-o", "--options=VALUE", "Connection string options") { |v| options = v }
parser.on("-d", "--duration=SECONDS", "Specifies the duration in seconds") { |v| duration = v.to_i }
parser.on("-c", "--concurrency=VALUE", "Specifies the concurrent requests to perform") { |v| concurrency = v.to_i }
parser.on("-h", "--help", "Show this help") do
puts parser
exit
end
parser.invalid_option do |flag|
STDERR.puts "ERROR: #{flag} is not a valid option."
STDERR.puts parser
exit(1)
end
end
multi_threaded = {% if flag?(:preview_mt) %} ENV["CRYSTAL_WORKERS"]?.try(&.to_i?) || 4 {% else %} false {% end %}
release = {% if flag?(:release) %} true {% else %} false {% end %}
if !release
puts "WARNING: This should be run in release mode."
end
db = DB.open "dummy://host?#{options}"
start_time = Time.monotonic
puts "Starting test for #{duration} seconds..."
concurrency.times do
spawn do
loop do
db.scalar "1"
Fiber.yield
end
end
end
sleep duration.seconds
end_time = Time.monotonic
puts " Options : #{options}"
puts " Duration (sec) : #{duration} (actual #{end_time - start_time})"
puts " Concurrency : #{concurrency}"
puts " Multi Threaded : #{multi_threaded ? "Yes (#{multi_threaded})" : "No"}"
puts "Total Connections : #{DummyDriver::DummyConnection.connections_count}"
puts " Total Statements : #{DummyDriver::DummyStatement.statements_count}"
puts " Total Queries : #{DummyDriver::DummyStatement.statements_exec_count}"
puts "Throughtput (q/s) : #{DummyDriver::DummyStatement.statements_exec_count / duration}"
if !release
puts "WARNING: This should be run in release mode."
end