Permalink
Browse files

Use TCP_NODELAY if supported; Remove file descriptor ops from the tig…

…ht 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.
  • Loading branch information...
1 parent 6c2b9ec commit 6884d454bcb5377ffee61110ccd1e6e75abce096 @methodmissing methodmissing committed Sep 9, 2008
Showing with 65 additions and 31 deletions.
  1. +19 −8 ext/mysql.c
  2. +2 −1 mysqlplus.gemspec
  3. +3 −20 test/{threaded_test.rb → c_threaded_test.rb}
  4. +6 −0 test/evented_test.rb
  5. +31 −0 test/native_threaded_test.rb
  6. +4 −2 test/test_helper.rb
View
@@ -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);
View
@@ -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",
@@ -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
View
@@ -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
@@ -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
View
@@ -13,14 +13,16 @@ class NotImplemented < StandardError
:start,
:done,
:c_async_query,
- :per_query_overhead
+ :per_query_overhead,
+ :timeout
def initialize( queries, context = '' )
@queries = queries
@context = context
@done = []
@c_async_query = false
@per_query_overhead = 3
+ @timeout = 20
yield self if block_given?
end
@@ -186,7 +188,7 @@ def prepare
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

6 comments on commit 6884d45

Collaborator

rdp replied Jan 12, 2009

I’m not sure if NILorSTRING returns ruby objects only…

Collaborator

rdp replied Jan 12, 2009

I’m not sure what vio_poll_read does—does it block? I wonder if we can skip the rb_select somehow…but this should be all right.

Collaborator

methodmissing replied Jan 12, 2009

Roger,

There’s also the option to use MYSQL_STATUS_READY, which libmysld sets as the status member of the Mysql struct.I found this to be slightly more reliable than vio_poll_read as the latter is best suited for poll, not select.

http://github.com/oldmoe/mysqlplus/commit/9d66a3b71e91688e4b4a90d056dbc8bbbb88dc7f

Collaborator

rdp replied Jan 12, 2009

so MYSQL_STATUS_READY means that the socket is ready for writing? Wow their docs seem so hard to parse…

Collaborator

rdp replied Mar 7, 2009

what does fastsend do do you know?
thanks!

Collaborator

methodmissing replied Mar 7, 2009

Roger,

Sets the TCP_NODELAY socket option

Please sign in to comment.