Permalink
Browse files

Selective enable || disable GC for result retrieval with Mysql#disabl…

…e_gc = true|false
  • Loading branch information...
1 parent 8e6f300 commit 35d2545c17f385a9cf524bfea39606524d75c009 @methodmissing methodmissing committed Oct 8, 2008
Showing with 46 additions and 9 deletions.
  1. +28 −9 ext/mysql.c
  2. +18 −0 test/gc_benchmark.rb
View
@@ -60,6 +60,7 @@ struct mysql {
MYSQL handler;
char connection;
char query_with_result;
+ char gc_disabled;
char blocking;
int async_in_progress;
};
@@ -181,7 +182,7 @@ static void mysql_raise(MYSQL* m)
rb_exc_raise(e);
}
-static VALUE mysqlres2obj(MYSQL_RES* res)
+static VALUE mysqlres2obj(MYSQL_RES* res, VALUE gc_disabled)
{
VALUE obj;
struct mysql_res* resp;
@@ -191,8 +192,9 @@ static VALUE mysqlres2obj(MYSQL_RES* res)
resp->res = res;
resp->freed = Qfalse;
rb_obj_call_init(obj, 0, NULL);
- if (++store_result_count > GC_STORE_RESULT_LIMIT)
- rb_gc();
+ if (++store_result_count > GC_STORE_RESULT_LIMIT && gc_disabled == Qfalse){
+ rb_gc();
+ }
return obj;
}
@@ -228,6 +230,7 @@ static VALUE init(VALUE klass)
mysql_init(&myp->handler);
myp->connection = Qfalse;
myp->query_with_result = Qtrue;
+ myp->gc_disabled = Qfalse;
rb_obj_call_init(obj, 0, NULL);
return obj;
}
@@ -646,7 +649,7 @@ static VALUE list_fields(int argc, VALUE* argv, VALUE obj)
res = mysql_list_fields(m, StringValuePtr(table), NILorSTRING(field));
if (res == NULL)
mysql_raise(m);
- return mysqlres2obj(res);
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
}
/* list_processes() */
@@ -656,7 +659,7 @@ static VALUE list_processes(VALUE obj)
MYSQL_RES* res = mysql_list_processes(m);
if (res == NULL)
mysql_raise(m);
- return mysqlres2obj(res);
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
}
/* list_tables(table=nil) */
@@ -750,7 +753,7 @@ static VALUE store_result(VALUE obj)
MYSQL_RES* res = mysql_store_result(m);
if (res == NULL)
mysql_raise(m);
- return mysqlres2obj(res);
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
}
/* thread_id() */
@@ -766,7 +769,7 @@ static VALUE use_result(VALUE obj)
MYSQL_RES* res = mysql_use_result(m);
if (res == NULL)
mysql_raise(m);
- return mysqlres2obj(res);
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
}
static VALUE res_free(VALUE);
@@ -788,7 +791,7 @@ static VALUE query(VALUE obj, VALUE sql)
if (mysql_field_count(m) != 0)
mysql_raise(m);
} else {
- VALUE robj = mysqlres2obj(res);
+ VALUE robj = mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
rb_ensure(rb_yield, robj, res_free, robj);
}
#if MYSQL_VERSION_ID >= 40101
@@ -859,6 +862,20 @@ static VALUE reconnected( VALUE obj ){
return ( current_connection_id == mysql_thread_id( m ) ) ? Qfalse : Qtrue;
}
+/* disable_gc(true|false) */
+static VALUE disable_gc_set(VALUE obj, VALUE flag)
+{
+ if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE)
+ rb_raise(rb_eTypeError, "invalid type, required true or false.");
+ GetMysqlStruct(obj)->gc_disabled = flag;
+ return flag;
+}
+
+/* gc_disabled */
+static VALUE gc_disabled( VALUE obj ){
+ return GetMysqlStruct(obj)->gc_disabled ? Qtrue: Qfalse;
+}
+
static void validate_async_query( VALUE obj )
{
MYSQL* m = GetHandler(obj);
@@ -1986,7 +2003,7 @@ static VALUE stmt_result_metadata(VALUE obj)
mysql_stmt_raise(s->stmt);
return Qnil;
}
- return mysqlres2obj(res);
+ return mysqlres2obj(res, Qfalse);
}
/* row_seek(offset) */
@@ -2254,6 +2271,8 @@ void Init_mysql(void)
rb_define_method(cMysql, "retry?", retry, 0);
rb_define_method(cMysql, "interrupted?", interrupted, 0);
rb_define_method(cMysql, "blocking?", blocking, 0);
+ rb_define_method(cMysql, "gc_disabled?", gc_disabled, 0);
+ rb_define_method(cMysql, "disable_gc=", disable_gc_set, 1);
rb_define_method(cMysql, "socket", socket, 0);
rb_define_method(cMysql, "refresh", refresh, 1);
rb_define_method(cMysql, "reload", reload, 0);
View
@@ -0,0 +1,18 @@
+require 'rubygems'
+require 'mysqlplus'
+require 'benchmark'
+
+with_gc = Mysql.real_connect('localhost','root','','mysql')
+without_gc = Mysql.real_connect('localhost','root','','mysql')
+without_gc.disable_gc = true
+
+n = 1000
+Benchmark.bm do |x|
+ x.report( 'With GC' ) do
+ n.times{ with_gc.c_async_query( 'SELECT * FROM user' ) }
+ end
+ GC.start
+ x.report( 'Without GC' ) do
+ n.times{ without_gc.c_async_query( 'SELECT * FROM user' ) }
+ end
+end

0 comments on commit 35d2545

Please sign in to comment.