Avoid INT2NUM overhead when coercing date specific elements for MYSQL_TYPE_TIME + introduce basic infrastructure for measuring GC overhead

This commit is contained in:
Lourens Naudé 2010-08-08 23:02:28 +01:00 committed by Brian Lopez
parent d9153b82fc
commit 2609783aeb
3 changed files with 41 additions and 5 deletions

View File

@ -47,7 +47,7 @@ namespace :bench do
define_bench_task :query_with_mysql_casting define_bench_task :query_with_mysql_casting
define_bench_task :query_without_mysql_casting define_bench_task :query_without_mysql_casting
define_bench_task :sequel define_bench_task :sequel
define_bench_task :allocations
end end
# Load custom tasks # Load custom tasks
Dir['tasks/*.rake'].sort.each { |f| load f } Dir['tasks/*.rake'].sort.each { |f| load f }

33
benchmark/allocations.rb Normal file
View File

@ -0,0 +1,33 @@
# encoding: UTF-8
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
raise Mysql2::Mysql2Error.new("GC allocation benchmarks only supported on Ruby 1.9!") unless RUBY_VERSION =~ /1\.9/
require 'rubygems'
require 'benchmark'
require 'active_record'
ActiveRecord::Base.default_timezone = :local
ActiveRecord::Base.time_zone_aware_attributes = true
class Mysql2Model < ActiveRecord::Base
set_table_name :mysql2_test
end
def bench_allocations(feature, iterations = 10, &blk)
puts "GC overhead for #{feature}"
Mysql2Model.establish_connection(:adapter => 'mysql2', :database => 'test')
GC::Profiler.clear
GC::Profiler.enable
iterations.times{ blk.call }
GC::Profiler.report(STDOUT)
GC::Profiler.disable
end
bench_allocations('coercion') do
Mysql2Model.all(:limit => 1000).each{ |r|
r.attributes.keys.each{ |k|
r.send(k.to_sym)
}
}
end

View File

@ -6,7 +6,7 @@ rb_encoding *binaryEncoding;
VALUE cMysql2Result; VALUE cMysql2Result;
VALUE cBigDecimal, cDate, cDateTime; VALUE cBigDecimal, cDate, cDateTime;
VALUE opt_decimal_zero, opt_float_zero; VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month;
extern VALUE mMysql2, cMysql2Client, cMysql2Error; extern VALUE mMysql2, cMysql2Client, cMysql2Error;
static VALUE intern_encoding_from_charset; static VALUE intern_encoding_from_charset;
static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code, static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code,
@ -96,7 +96,6 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
MYSQL_FIELD * fields = NULL; MYSQL_FIELD * fields = NULL;
unsigned int i = 0; unsigned int i = 0;
unsigned long * fieldLengths; unsigned long * fieldLengths;
double column_to_double;
void * ptr; void * ptr;
#ifdef HAVE_RUBY_ENCODING_H #ifdef HAVE_RUBY_ENCODING_H
rb_encoding *default_internal_enc = rb_default_internal_encoding(); rb_encoding *default_internal_enc = rb_default_internal_encoding();
@ -155,7 +154,8 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
} }
break; break;
case MYSQL_TYPE_FLOAT: // FLOAT field case MYSQL_TYPE_FLOAT: // FLOAT field
case MYSQL_TYPE_DOUBLE: // DOUBLE or REAL field case MYSQL_TYPE_DOUBLE: { // DOUBLE or REAL field
double column_to_double;
column_to_double = strtod(row[i], NULL); column_to_double = strtod(row[i], NULL);
if (column_to_double == 0.000000){ if (column_to_double == 0.000000){
val = opt_float_zero; val = opt_float_zero;
@ -163,10 +163,11 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
val = rb_float_new(column_to_double); val = rb_float_new(column_to_double);
} }
break; break;
}
case MYSQL_TYPE_TIME: { // TIME field case MYSQL_TYPE_TIME: { // TIME field
int hour, min, sec, tokens; int hour, min, sec, tokens;
tokens = sscanf(row[i], "%2d:%2d:%2d", &hour, &min, &sec); tokens = sscanf(row[i], "%2d:%2d:%2d", &hour, &min, &sec);
val = rb_funcall(rb_cTime, db_timezone, 6, INT2NUM(2000), INT2NUM(1), INT2NUM(1), INT2NUM(hour), INT2NUM(min), INT2NUM(sec)); val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
if (!NIL_P(app_timezone)) { if (!NIL_P(app_timezone)) {
if (app_timezone == intern_local) { if (app_timezone == intern_local) {
val = rb_funcall(val, intern_localtime, 0); val = rb_funcall(val, intern_localtime, 0);
@ -435,6 +436,8 @@ void init_mysql2_result() {
opt_decimal_zero = rb_str_new2("0.0"); opt_decimal_zero = rb_str_new2("0.0");
rb_global_variable(&opt_float_zero); rb_global_variable(&opt_float_zero);
opt_float_zero = rb_float_new((double)0); opt_float_zero = rb_float_new((double)0);
opt_time_year = INT2NUM(2000);
opt_time_month = INT2NUM(1);
#ifdef HAVE_RUBY_ENCODING_H #ifdef HAVE_RUBY_ENCODING_H
binaryEncoding = rb_enc_find("binary"); binaryEncoding = rb_enc_find("binary");