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/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
@@ -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
+