oldmoe-mysqlplus 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +32 -0
- data/Rakefile +52 -0
- data/ext/error_const.h +536 -0
- data/ext/extconf.rb +74 -0
- data/ext/mysql.c +2461 -0
- data/lib/mysqlplus.rb +19 -0
- data/mysqlplus.gemspec +29 -0
- data/test/c_threaded_test.rb +36 -0
- data/test/evented_test.rb +31 -0
- data/test/native_threaded_test.rb +31 -0
- data/test/test_helper.rb +200 -0
- metadata +64 -0
data/lib/mysqlplus.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'mysql'
|
2
|
+
|
3
|
+
class Mysql
|
4
|
+
|
5
|
+
def async_query(sql, timeout = nil)
|
6
|
+
send_query(sql)
|
7
|
+
select [ (@sockets ||= {})[socket] ||= IO.new(socket) ], nil, nil, nil
|
8
|
+
get_result
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
class Mysql::Result
|
14
|
+
def all_hashes
|
15
|
+
rows = []
|
16
|
+
each_hash { |row| rows << row }
|
17
|
+
rows
|
18
|
+
end
|
19
|
+
end
|
data/mysqlplus.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "mysqlplus"
|
3
|
+
s.version = "0.1.0"
|
4
|
+
s.date = "2008-08-13"
|
5
|
+
s.summary = "Enhanced Ruby MySQL driver"
|
6
|
+
s.email = "oldmoe@gmail.com"
|
7
|
+
s.homepage = "http://github.com/oldmoe/mysqlplus"
|
8
|
+
s.description = "Enhanced Ruby MySQL driver"
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.authors = ["Muhammad A. Ali"]
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.files = [
|
13
|
+
"mysqlplus.gemspec",
|
14
|
+
"README",
|
15
|
+
"Rakefile",
|
16
|
+
"lib/mysqlplus.rb",
|
17
|
+
"test/test_helper.rb",
|
18
|
+
"test/native_threaded_test.rb",
|
19
|
+
"test/c_threaded_test.rb",
|
20
|
+
"test/evented_test.rb",
|
21
|
+
"ext/error_const.h",
|
22
|
+
"ext/extconf.rb",
|
23
|
+
"ext/mysql.c"
|
24
|
+
]
|
25
|
+
s.rdoc_options = ["--main", "README"]
|
26
|
+
s.extra_rdoc_files = ["README"]
|
27
|
+
s.extensions << "ext/extconf.rb"
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
ThreadedMysqlTest.new( 10, "Threaded, C, very small overhead" ) do |test|
|
4
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
5
|
+
test.per_query_overhead = 0.005
|
6
|
+
test.c_async_query = true
|
7
|
+
test.run!
|
8
|
+
end
|
9
|
+
|
10
|
+
ThreadedMysqlTest.new( 10, "Threaded, C, small overhead" ) do |test|
|
11
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
12
|
+
test.per_query_overhead = 0.1
|
13
|
+
test.c_async_query = true
|
14
|
+
test.run!
|
15
|
+
end
|
16
|
+
|
17
|
+
ThreadedMysqlTest.new( 10, "Threaded, C, medium overhead" ) do |test|
|
18
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
19
|
+
test.per_query_overhead = 1
|
20
|
+
test.c_async_query = true
|
21
|
+
test.run!
|
22
|
+
end
|
23
|
+
|
24
|
+
ThreadedMysqlTest.new( 10, "Threaded, C, large overhead" ) do |test|
|
25
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
26
|
+
test.per_query_overhead = 3
|
27
|
+
test.c_async_query = true
|
28
|
+
test.run!
|
29
|
+
end
|
30
|
+
|
31
|
+
ThreadedMysqlTest.new( 10, "Threaded, C, random overhead" ) do |test|
|
32
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
33
|
+
test.per_query_overhead = :random
|
34
|
+
test.c_async_query = true
|
35
|
+
test.run!
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
EventedMysqlTest.new( 10, "Evented, very small overhead" ) do |test|
|
4
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
5
|
+
test.per_query_overhead = 0.005
|
6
|
+
test.run!
|
7
|
+
end
|
8
|
+
|
9
|
+
EventedMysqlTest.new( 10, "Evented, small overhead" ) do |test|
|
10
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
11
|
+
test.per_query_overhead = 0.1
|
12
|
+
test.run!
|
13
|
+
end
|
14
|
+
|
15
|
+
EventedMysqlTest.new( 10, "Evented, medium overhead" ) do |test|
|
16
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
17
|
+
test.per_query_overhead = 1
|
18
|
+
test.run!
|
19
|
+
end
|
20
|
+
|
21
|
+
EventedMysqlTest.new( 10, "Evented, large overhead" ) do |test|
|
22
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
23
|
+
test.per_query_overhead = 3
|
24
|
+
test.run!
|
25
|
+
end
|
26
|
+
|
27
|
+
EventedMysqlTest.new( 10, "Evented, random overhead" ) do |test|
|
28
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
29
|
+
test.per_query_overhead = :random
|
30
|
+
test.run!
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
ThreadedMysqlTest.new( 10, "Threaded, native Ruby, very small overhead" ) do |test|
|
4
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
5
|
+
test.per_query_overhead = 0.005
|
6
|
+
test.run!
|
7
|
+
end
|
8
|
+
|
9
|
+
ThreadedMysqlTest.new( 10, "Threaded, native Ruby, small overhead" ) do |test|
|
10
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
11
|
+
test.per_query_overhead = 0.1
|
12
|
+
test.run!
|
13
|
+
end
|
14
|
+
|
15
|
+
ThreadedMysqlTest.new( 10, "Threaded, native Ruby, medium overhead" ) do |test|
|
16
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
17
|
+
test.per_query_overhead = 1
|
18
|
+
test.run!
|
19
|
+
end
|
20
|
+
|
21
|
+
ThreadedMysqlTest.new( 10, "Threaded, native Ruby, large overhead" ) do |test|
|
22
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
23
|
+
test.per_query_overhead = 3
|
24
|
+
test.run!
|
25
|
+
end
|
26
|
+
|
27
|
+
ThreadedMysqlTest.new( 10, "Threaded, native Ruby, random overhead" ) do |test|
|
28
|
+
test.setup{ Mysql.real_connect('localhost','root') }
|
29
|
+
test.per_query_overhead = :random
|
30
|
+
test.run!
|
31
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mysqlplus'
|
3
|
+
|
4
|
+
class MysqlTest
|
5
|
+
|
6
|
+
class NotImplemented < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :queries,
|
10
|
+
:context,
|
11
|
+
:connections,
|
12
|
+
:connection_signature,
|
13
|
+
:start,
|
14
|
+
:done,
|
15
|
+
:c_async_query,
|
16
|
+
:per_query_overhead,
|
17
|
+
:timeout
|
18
|
+
|
19
|
+
def initialize( queries, context = '' )
|
20
|
+
@queries = queries
|
21
|
+
@context = context
|
22
|
+
@done = []
|
23
|
+
@c_async_query = false
|
24
|
+
@per_query_overhead = 3
|
25
|
+
@timeout = 20
|
26
|
+
yield self if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup( &block )
|
30
|
+
@start = Time.now
|
31
|
+
@connection_signature = block
|
32
|
+
end
|
33
|
+
|
34
|
+
def run!
|
35
|
+
c_or_native_ruby_async_query do
|
36
|
+
present_context if context?
|
37
|
+
prepare
|
38
|
+
yield
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def per_query_overhead=( overhead )
|
43
|
+
@per_query_overhead = ( overhead == :random ) ? rand() : overhead
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def prepare
|
49
|
+
raise NotImplemented
|
50
|
+
end
|
51
|
+
|
52
|
+
def teardown
|
53
|
+
raise NotImplemented
|
54
|
+
end
|
55
|
+
|
56
|
+
def log( message, prefix = '' )
|
57
|
+
puts "[#{timestamp}] #{prefix} #{message}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def with_logging( message )
|
61
|
+
log( message, 'Start' )
|
62
|
+
yield
|
63
|
+
log( message, 'End' )
|
64
|
+
end
|
65
|
+
|
66
|
+
def timestamp
|
67
|
+
Time.now - @start
|
68
|
+
end
|
69
|
+
|
70
|
+
def context?
|
71
|
+
@context != ''
|
72
|
+
end
|
73
|
+
|
74
|
+
def present_context
|
75
|
+
log "#############################################"
|
76
|
+
log "# #{@context}"
|
77
|
+
log "#############################################"
|
78
|
+
end
|
79
|
+
|
80
|
+
def c_or_native_ruby_async_query
|
81
|
+
if @c_async_query
|
82
|
+
log "** using C based async_query"
|
83
|
+
else
|
84
|
+
log "** using native Ruby async_query"
|
85
|
+
end
|
86
|
+
yield
|
87
|
+
end
|
88
|
+
|
89
|
+
def c_or_native_async_query( connection, sql, timeout = nil )
|
90
|
+
method = @c_async_query ? :c_async_query : :async_query
|
91
|
+
connection.send( method, sql, timeout )
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
class EventedMysqlTest < MysqlTest
|
97
|
+
|
98
|
+
attr_accessor :sockets
|
99
|
+
|
100
|
+
def initialize( queries, context = '' )
|
101
|
+
@sockets = []
|
102
|
+
@connections = {}
|
103
|
+
super( queries, context )
|
104
|
+
end
|
105
|
+
|
106
|
+
def setup( &block )
|
107
|
+
super( &block )
|
108
|
+
with_logging 'Setup connection pool' do
|
109
|
+
@queries.times do
|
110
|
+
connection = @connection_signature.call
|
111
|
+
@connections[ IO.new(connection.socket) ] = connection
|
112
|
+
@sockets = @connections.keys
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def run!
|
118
|
+
super do
|
119
|
+
catch :END_EVENT_LOOP do
|
120
|
+
loop do
|
121
|
+
result = select( @sockets,nil,nil,nil )
|
122
|
+
if result
|
123
|
+
result.first.each do |conn|
|
124
|
+
@connections[conn].get_result.each{|res| log( "Result for socket #{conn.fileno} : #{res}" ) }
|
125
|
+
@done << nil
|
126
|
+
if done?
|
127
|
+
teardown
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
|
138
|
+
def prepare
|
139
|
+
@connections.each_value do |conn|
|
140
|
+
conn.send_query( "select sleep(#{@per_query_overhead})" )
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def teardown
|
145
|
+
log "done"
|
146
|
+
throw :END_EVENT_LOOP
|
147
|
+
end
|
148
|
+
|
149
|
+
def done?
|
150
|
+
@done.size == @queries
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
class ThreadedMysqlTest < MysqlTest
|
156
|
+
|
157
|
+
attr_accessor :threads
|
158
|
+
|
159
|
+
def initialize( queries, context = '' )
|
160
|
+
@connections = []
|
161
|
+
@threads = []
|
162
|
+
super( queries, context )
|
163
|
+
end
|
164
|
+
|
165
|
+
def setup( &block )
|
166
|
+
super( &block )
|
167
|
+
with_logging "Setup connection pool" do
|
168
|
+
@queries.times do
|
169
|
+
@connections << @connection_signature.call
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def run!
|
175
|
+
super do
|
176
|
+
with_logging "waiting on threads" do
|
177
|
+
@threads.each{|t| t.join }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
protected
|
183
|
+
|
184
|
+
def prepare
|
185
|
+
with_logging "prepare" do
|
186
|
+
@queries.times do |conn|
|
187
|
+
@threads << Thread.new do
|
188
|
+
|
189
|
+
log "sending query on connection #{conn}"
|
190
|
+
|
191
|
+
c_or_native_async_query( @connections[conn], "select sleep(#{@per_query_overhead})", @timeout ).each do |result|
|
192
|
+
log "connection #{conn} done"
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oldmoe-mysqlplus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Muhammad A. Ali
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-08-13 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Enhanced Ruby MySQL driver
|
17
|
+
email: oldmoe@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- ext/extconf.rb
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- mysqlplus.gemspec
|
26
|
+
- README
|
27
|
+
- Rakefile
|
28
|
+
- lib/mysqlplus.rb
|
29
|
+
- test/test_helper.rb
|
30
|
+
- test/native_threaded_test.rb
|
31
|
+
- test/c_threaded_test.rb
|
32
|
+
- test/evented_test.rb
|
33
|
+
- ext/error_const.h
|
34
|
+
- ext/extconf.rb
|
35
|
+
- ext/mysql.c
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://github.com/oldmoe/mysqlplus
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --main
|
41
|
+
- README
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.2.0
|
60
|
+
signing_key:
|
61
|
+
specification_version: 2
|
62
|
+
summary: Enhanced Ruby MySQL driver
|
63
|
+
test_files: []
|
64
|
+
|