From ea2965270c89b30b00831673e4c09cdd9fc8ce67 Mon Sep 17 00:00:00 2001 From: Lourens Naude Date: Mon, 8 Sep 2008 17:27:11 +0100 Subject: [PATCH 1/2] Decouple native Ruby Mysql#async_query from the C extension as per Roger's suggestion.Remove no-op c_mysql_query flag for evented tests. --- ext/extconf.rb | 4 ++++ ext/mysql.c | 2 +- lib/mysqlplus.rb | 4 ---- test/evented_test.rb | 7 ------- test/test_helper.rb | 20 ++++++-------------- test/threaded_test.rb | 1 - 6 files changed, 11 insertions(+), 27 deletions(-) diff --git a/ext/extconf.rb b/ext/extconf.rb index bc00612..20252cc 100644 --- a/ext/extconf.rb +++ b/ext/extconf.rb @@ -31,6 +31,10 @@ else exit 1 end +if have_func('rb_thread_blocking_region') and have_macro('RB_UBF_DFL', 'ruby.h') + flags << "-DHAVE_TBR" +end + # make mysql constant File.open("conftest.c", "w") do |f| f.puts src diff --git a/ext/mysql.c b/ext/mysql.c index 739d352..e6496db 100644 --- a/ext/mysql.c +++ b/ext/mysql.c @@ -2143,7 +2143,7 @@ void Init_mysql(void) #endif rb_define_method(cMysql, "query", query, 1); rb_define_method(cMysql, "real_query", query, 1); - rb_define_method(cMysql, "async_query", async_query, -1); + rb_define_method(cMysql, "c_async_query", async_query, -1); rb_define_method(cMysql, "send_query", send_query, 1); rb_define_method(cMysql, "get_result", get_result, 0); rb_define_method(cMysql, "readable?", readable, -1); diff --git a/lib/mysqlplus.rb b/lib/mysqlplus.rb index 48fa44a..95fa6c4 100644 --- a/lib/mysqlplus.rb +++ b/lib/mysqlplus.rb @@ -2,11 +2,7 @@ require 'mysql' class Mysql - alias_method :c_async_query, :async_query - def async_query(sql, timeout = nil) - puts "** Blocking ? #{blocking?().inspect}" if ENV['MYSQL_BLOCKING_STATUS'] == '1' - return c_async_query(sql, timeout) if ENV['MYSQL_C_ASYNC_QUERY'] == '1' send_query(sql) select [ (@sockets ||= {})[socket] ||= IO.new(socket) ], nil, nil, nil get_result diff --git a/test/evented_test.rb b/test/evented_test.rb index 0155db4..ec8ad3d 100644 --- a/test/evented_test.rb +++ b/test/evented_test.rb @@ -2,12 +2,5 @@ require File.dirname(__FILE__) + '/test_helper' EventedMysqlTest.new( 10 ) do |test| test.setup{ Mysql.real_connect('localhost','root') } - test.log_blocking_status = true - test.run! -end - -EventedMysqlTest.new( 10 ) do |test| - test.setup{ Mysql.real_connect('localhost','root') } - test.c_async_query = true test.run! end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 4e5c96e..df0ea47 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -28,10 +28,8 @@ class MysqlTest def run! c_or_native_ruby_async_query do - with_blocking_status do - prepare - yield - end + prepare + yield end end @@ -61,22 +59,16 @@ class MysqlTest def c_or_native_ruby_async_query if @c_async_query - ENV['MYSQL_C_ASYNC_QUERY'] = '1' log "** using C based async_query" else - ENV['MYSQL_C_ASYNC_QUERY'] = '0' log "** using native Ruby async_query" end yield end - def with_blocking_status - if @log_blocking_status - ENV['MYSQL_BLOCKING_STATUS'] = '1' - else - ENV['MYSQL_BLOCKING_STATUS'] = '0' - end - yield + def c_or_native_async_query( connection, sql, timeout = nil ) + method = @c_async_query ? :c_async_query : :async_query + connection.send( method, sql, timeout ) end end @@ -174,7 +166,7 @@ class ThreadedMysqlTest < MysqlTest log "sending query on connection #{conn}" - @connections[conn].async_query( "select sleep(3)" ).each do |result| + c_or_native_async_query( @connections[conn], "select sleep(3)" ).each do |result| log "connection #{conn} done" end diff --git a/test/threaded_test.rb b/test/threaded_test.rb index 122c817..5a70158 100644 --- a/test/threaded_test.rb +++ b/test/threaded_test.rb @@ -2,7 +2,6 @@ require File.dirname(__FILE__) + '/test_helper' ThreadedMysqlTest.new( 10 ) do |test| test.setup{ Mysql.real_connect('localhost','root') } - test.log_blocking_status = true test.run! end From f077108a69c400a29ba1deaf85dd040c76084d0b Mon Sep 17 00:00:00 2001 From: Lourens Naude Date: Mon, 8 Sep 2008 17:45:00 +0100 Subject: [PATCH 2/2] Introduce configureable query overheads and contexts in the test wrapper in preparation for timeout tests. --- test/evented_test.rb | 21 +++++++++++++++++++- test/test_helper.rb | 42 +++++++++++++++++++++++++++++----------- test/threaded_test.rb | 45 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 14 deletions(-) diff --git a/test/evented_test.rb b/test/evented_test.rb index ec8ad3d..271a7c8 100644 --- a/test/evented_test.rb +++ b/test/evented_test.rb @@ -1,6 +1,25 @@ require File.dirname(__FILE__) + '/test_helper' -EventedMysqlTest.new( 10 ) do |test| +EventedMysqlTest.new( 10, "Evented, small overhead" ) do |test| test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 0.1 + test.run! +end + +EventedMysqlTest.new( 10, "Evented, medium overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 1 + test.run! +end + +EventedMysqlTest.new( 10, "Evented, large overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 3 + test.run! +end + +EventedMysqlTest.new( 10, "Evented, random overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = :random test.run! end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index df0ea47..1d80ebf 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -7,17 +7,20 @@ class MysqlTest end attr_accessor :queries, + :context, :connections, :connection_signature, :start, :done, :c_async_query, - :log_blocking_status + :per_query_overhead - def initialize( queries ) + def initialize( queries, context = '' ) @queries = queries + @context = context @done = [] @c_async_query = false + @per_query_overhead = 3 yield self if block_given? end @@ -28,11 +31,18 @@ class MysqlTest def run! c_or_native_ruby_async_query do + present_context if context? prepare yield end end + def per_query_overhead=( overhead ) + @per_query_overhead = ( overhead == :random ) ? rand() : overhead + end + + protected + def prepare raise NotImplemented end @@ -54,8 +64,16 @@ class MysqlTest def timestamp Time.now - @start end + + def context? + @context != '' + end - protected + def present_context + log "#############################################" + log "# #{@context}" + log "#############################################" + end def c_or_native_ruby_async_query if @c_async_query @@ -77,10 +95,10 @@ class EventedMysqlTest < MysqlTest attr_accessor :sockets - def initialize( queries ) + def initialize( queries, context = '' ) @sockets = [] @connections = {} - super( queries ) + super( queries, context ) end def setup( &block ) @@ -113,9 +131,11 @@ class EventedMysqlTest < MysqlTest end end + protected + def prepare @connections.each_value do |conn| - conn.send_query( "select sleep(3)" ) + conn.send_query( "select sleep(#{@per_query_overhead})" ) end end @@ -124,8 +144,6 @@ class EventedMysqlTest < MysqlTest throw :END_EVENT_LOOP end - protected - def done? @done.size == @queries end @@ -136,10 +154,10 @@ class ThreadedMysqlTest < MysqlTest attr_accessor :threads - def initialize( queries ) + def initialize( queries, context = '' ) @connections = [] @threads = [] - super( queries ) + super( queries, context ) end def setup( &block ) @@ -159,6 +177,8 @@ class ThreadedMysqlTest < MysqlTest end end + protected + def prepare with_logging "prepare" do @queries.times do |conn| @@ -166,7 +186,7 @@ class ThreadedMysqlTest < MysqlTest log "sending query on connection #{conn}" - c_or_native_async_query( @connections[conn], "select sleep(3)" ).each do |result| + c_or_native_async_query( @connections[conn], "select sleep(#{@per_query_overhead})" ).each do |result| log "connection #{conn} done" end diff --git a/test/threaded_test.rb b/test/threaded_test.rb index 5a70158..74927bf 100644 --- a/test/threaded_test.rb +++ b/test/threaded_test.rb @@ -1,12 +1,53 @@ require File.dirname(__FILE__) + '/test_helper' -ThreadedMysqlTest.new( 10 ) do |test| +ThreadedMysqlTest.new( 10, "Threaded, native Ruby, small overhead" ) do |test| test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 0.1 test.run! end -ThreadedMysqlTest.new( 10 ) do |test| +ThreadedMysqlTest.new( 10, "Threaded, native Ruby, medium overhead" ) do |test| test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 1 + test.run! +end + +ThreadedMysqlTest.new( 10, "Threaded, native Ruby, large overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 3 + test.run! +end + +ThreadedMysqlTest.new( 10, "Threaded, native Ruby, random overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = :random + test.run! +end + +ThreadedMysqlTest.new( 10, "Threaded, C, small overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 0.1 + test.c_async_query = true + test.run! +end + +ThreadedMysqlTest.new( 10, "Threaded, C, medium overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 1 + test.c_async_query = true + test.run! +end + +ThreadedMysqlTest.new( 10, "Threaded, C, large overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 3 + test.c_async_query = true + test.run! +end + +ThreadedMysqlTest.new( 10, "Threaded, C, random overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = :random test.c_async_query = true test.run! end \ No newline at end of file