From 6884d454bcb5377ffee61110ccd1e6e75abce096 Mon Sep 17 00:00:00 2001 From: Lourens Naude Date: Wed, 10 Sep 2008 00:33:18 +0100 Subject: [PATCH] Use TCP_NODELAY if supported; Remove file descriptor ops from the tight loop; Cleanup timeout assignment; Split the threaded test suite in native and c to avoid a large number of active Threads affecting results.Add experimental Mysql#socket_type which typically returns 'socket (x)', but may be helpful for debugging purposes. --- ext/mysql.c | 27 +++++++++++----- mysqlplus.gemspec | 3 +- test/{threaded_test.rb => c_threaded_test.rb} | 23 ++------------ test/evented_test.rb | 6 ++++ test/native_threaded_test.rb | 31 +++++++++++++++++++ test/test_helper.rb | 6 ++-- 6 files changed, 65 insertions(+), 31 deletions(-) rename test/{threaded_test.rb => c_threaded_test.rb} (58%) create mode 100644 test/native_threaded_test.rb diff --git a/ext/mysql.c b/ext/mysql.c index da03f55..f0cb8d0 100644 --- a/ext/mysql.c +++ b/ext/mysql.c @@ -269,11 +269,14 @@ static VALUE real_connect(int argc, VALUE* argv, VALUE klass) myp->handler.reconnect = 0; myp->connection = Qtrue; - + my_bool was_blocking; + vio_blocking(myp->handler.net.vio, 0, &was_blocking); myp->blocking = vio_is_blocking( myp->handler.net.vio ); + vio_fastsend( myp->handler.net.vio ); + myp->query_with_result = Qtrue; rb_obj_call_init(obj, argc, argv); @@ -762,6 +765,14 @@ static VALUE socket(VALUE obj) return INT2NUM(m->net.fd); } +/* socket_type */ +static VALUE socket_type(VALUE obj) +{ + MYSQL* m = GetHandler(obj); + VALUE description = vio_description( m->net.vio ); + return NILorSTRING( description ); +} + /* blocking */ static VALUE blocking(VALUE obj){ return ( GetMysqlStruct(obj)->blocking ? Qtrue : Qfalse ); @@ -825,28 +836,27 @@ static VALUE async_query(int argc, VALUE* argv, VALUE obj) send_query(obj,sql); - if (NIL_P(timeout)) { - timeout = m->net.read_timeout; - } + timeout = ( NIL_P(timeout) ? m->net.read_timeout : INT2NUM(timeout) ); VALUE args[1]; args[0] = timeout; struct timeval tv = { tv_sec: timeout, tv_usec: 0 }; + FD_ZERO(&read); + FD_SET(m->net.fd, &read); + for(;;) { - FD_ZERO(&read); - FD_SET(m->net.fd, &read); ret = rb_thread_select(m->net.fd + 1, &read, NULL, NULL, &tv); if (ret < 0) { - rb_sys_fail(0); + rb_raise(eMysql, "query: timeout"); } if (ret == 0) { continue; } - if (readable(1, (VALUE *)args, obj) == Qtrue) { + if ( vio_poll_read( m->net.vio, INT2NUM(timeout) ) == 0 ) { break; } } @@ -2147,6 +2157,7 @@ void Init_mysql(void) rb_define_method(cMysql, "readable?", readable, -1); rb_define_method(cMysql, "blocking?", blocking, 0); rb_define_method(cMysql, "socket", socket, 0); + rb_define_method(cMysql, "socket_type", socket_type, 0); rb_define_method(cMysql, "refresh", refresh, 1); rb_define_method(cMysql, "reload", reload, 0); rb_define_method(cMysql, "select_db", select_db, 1); diff --git a/mysqlplus.gemspec b/mysqlplus.gemspec index 9d8c492..3cf754e 100755 --- a/mysqlplus.gemspec +++ b/mysqlplus.gemspec @@ -15,7 +15,8 @@ Gem::Specification.new do |s| "Rakefile", "lib/mysqlplus.rb", "test/test_helper.rb", - "test/threaded_test.rb", + "test/native_threaded_test.rb", + "test/c_threaded_test.rb", "test/evented_test.rb", "ext/error_const.h", "ext/extconf.rb", diff --git a/test/threaded_test.rb b/test/c_threaded_test.rb similarity index 58% rename from test/threaded_test.rb rename to test/c_threaded_test.rb index 74927bf..49d6245 100644 --- a/test/threaded_test.rb +++ b/test/c_threaded_test.rb @@ -1,26 +1,9 @@ require File.dirname(__FILE__) + '/test_helper' -ThreadedMysqlTest.new( 10, "Threaded, native Ruby, small overhead" ) do |test| +ThreadedMysqlTest.new( 10, "Threaded, C, very small overhead" ) do |test| test.setup{ Mysql.real_connect('localhost','root') } - test.per_query_overhead = 0.1 - test.run! -end - -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.per_query_overhead = 0.005 + test.c_async_query = true test.run! end diff --git a/test/evented_test.rb b/test/evented_test.rb index 271a7c8..292a4b8 100644 --- a/test/evented_test.rb +++ b/test/evented_test.rb @@ -1,5 +1,11 @@ require File.dirname(__FILE__) + '/test_helper' +EventedMysqlTest.new( 10, "Evented, very small overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 0.005 + test.run! +end + EventedMysqlTest.new( 10, "Evented, small overhead" ) do |test| test.setup{ Mysql.real_connect('localhost','root') } test.per_query_overhead = 0.1 diff --git a/test/native_threaded_test.rb b/test/native_threaded_test.rb new file mode 100644 index 0000000..24d35b7 --- /dev/null +++ b/test/native_threaded_test.rb @@ -0,0 +1,31 @@ +require File.dirname(__FILE__) + '/test_helper' + +ThreadedMysqlTest.new( 10, "Threaded, native Ruby, very small overhead" ) do |test| + test.setup{ Mysql.real_connect('localhost','root') } + test.per_query_overhead = 0.005 + test.run! +end + +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, "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 \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 1d80ebf..3a69f21 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -13,7 +13,8 @@ class MysqlTest :start, :done, :c_async_query, - :per_query_overhead + :per_query_overhead, + :timeout def initialize( queries, context = '' ) @queries = queries @@ -21,6 +22,7 @@ class MysqlTest @done = [] @c_async_query = false @per_query_overhead = 3 + @timeout = 20 yield self if block_given? end @@ -186,7 +188,7 @@ class ThreadedMysqlTest < MysqlTest log "sending query on connection #{conn}" - c_or_native_async_query( @connections[conn], "select sleep(#{@per_query_overhead})" ).each do |result| + c_or_native_async_query( @connections[conn], "select sleep(#{@per_query_overhead})", @timeout ).each do |result| log "connection #{conn} done" end