Skip to content

Commit 13e5d59

Browse files
committed
Use benchmark/ips for ergonomics
1 parent 92ac260 commit 13e5d59

File tree

9 files changed

+121
-178
lines changed

9 files changed

+121
-178
lines changed

Gemfile

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@ gemspec
55
# benchmarks
66
group :benchmarks do
77
gem 'activerecord', '>= 3.0'
8-
gem 'mysql'
8+
gem 'benchmark-ips'
99
gem 'do_mysql'
10-
gem 'sequel'
1110
gem 'faker'
11+
gem 'mysql'
12+
gem 'sequel'
1213
end
1314

1415
group :development do
15-
gem 'pry'
1616
gem 'eventmachine' unless RUBY_PLATFORM =~ /mswin|mingw/
17+
gem 'pry'
1718
end
1819

1920
platforms :rbx do
20-
gem 'rubysl-rake'
21-
gem 'rubysl-drb'
2221
gem 'rubysl-bigdecimal'
22+
gem 'rubysl-drb'
23+
gem 'rubysl-rake'
2324
end

benchmark/active_record.rb

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,32 @@
22
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
33

44
require 'rubygems'
5-
require 'benchmark'
5+
require 'benchmark/ips'
66
require 'active_record'
77

88
ActiveRecord::Base.default_timezone = :local
99
ActiveRecord::Base.time_zone_aware_attributes = true
1010

11-
number_of = 10
12-
mysql2_opts = {
13-
:adapter => 'mysql2',
14-
:database => 'test'
15-
}
16-
mysql_opts = {
17-
:adapter => 'mysql',
18-
:database => 'test'
19-
}
20-
21-
class Mysql2Model < ActiveRecord::Base
22-
self.table_name = "mysql2_test"
23-
end
11+
opts = { :database => 'test' }
2412

25-
class MysqlModel < ActiveRecord::Base
26-
self.table_name = "mysql2_test"
13+
class TestModel < ActiveRecord::Base
14+
self.table_name = 'mysql2_test'
2715
end
2816

29-
Benchmark.bmbm do |x|
30-
x.report "Mysql2" do
31-
Mysql2Model.establish_connection(mysql2_opts)
32-
number_of.times do
33-
Mysql2Model.limit(1000).to_a.each{ |r|
34-
r.attributes.keys.each{ |k|
35-
r.send(k.to_sym)
36-
}
37-
}
38-
end
39-
end
17+
batch_size = 1000
18+
19+
Benchmark.ips do |x|
20+
%w(mysql mysql2).each do |adapter|
21+
TestModel.establish_connection(opts.merge(:adapter => adapter))
4022

41-
x.report "Mysql" do
42-
MysqlModel.establish_connection(mysql_opts)
43-
number_of.times do
44-
MysqlModel.limit(1000).to_a.each{ |r|
45-
r.attributes.keys.each{ |k|
23+
x.report(adapter) do
24+
TestModel.limit(batch_size).to_a.each do |r|
25+
r.attributes.keys.each do |k|
4626
r.send(k.to_sym)
47-
}
48-
}
27+
end
28+
end
4929
end
5030
end
31+
32+
x.compare!
5133
end

benchmark/active_record_threaded.rb

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,22 @@
22
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
33

44
require 'rubygems'
5-
require 'benchmark'
5+
require 'benchmark/ips'
66
require 'active_record'
77

8-
times = 25
8+
number_of_threads = 25
9+
opts = { :database => 'test', :pool => number_of_threads }
910

11+
Benchmark.ips do |x|
12+
%w(mysql mysql2).each do |adapter|
13+
ActiveRecord::Base.establish_connection(opts.merge(:adapter => adapter))
1014

11-
# mysql2
12-
mysql2_opts = {
13-
:adapter => 'mysql2',
14-
:database => 'test',
15-
:pool => times
16-
}
17-
ActiveRecord::Base.establish_connection(mysql2_opts)
18-
x = Benchmark.realtime do
19-
threads = []
20-
times.times do
21-
threads << Thread.new { ActiveRecord::Base.connection.execute("select sleep(1)") }
15+
x.report(adapter) do
16+
number_of_threads.times.map do
17+
Thread.new { ActiveRecord::Base.connection.execute('SELECT SLEEP(1)') }
18+
end.each(&:join)
19+
end
2220
end
23-
threads.each {|t| t.join }
24-
end
25-
puts "mysql2: #{x} seconds"
26-
2721

28-
# mysql
29-
mysql2_opts = {
30-
:adapter => 'mysql',
31-
:database => 'test',
32-
:pool => times
33-
}
34-
ActiveRecord::Base.establish_connection(mysql2_opts)
35-
x = Benchmark.realtime do
36-
threads = []
37-
times.times do
38-
threads << Thread.new { ActiveRecord::Base.connection.execute("select sleep(1)") }
39-
end
40-
threads.each {|t| t.join }
22+
x.compare!
4123
end
42-
puts "mysql: #{x} seconds"

benchmark/allocations.rb

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,31 @@
22
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
33

44
require 'rubygems'
5-
require 'benchmark'
65
require 'active_record'
76

87
raise Mysql2::Error.new("GC allocation benchmarks only supported on Ruby 1.9!") unless RUBY_VERSION > '1.9'
98

109
ActiveRecord::Base.default_timezone = :local
1110
ActiveRecord::Base.time_zone_aware_attributes = true
1211

13-
class Mysql2Model < ActiveRecord::Base
14-
self.table_name = "mysql2_test"
12+
class TestModel < ActiveRecord::Base
13+
self.table_name = 'mysql2_test'
1514
end
1615

17-
def bench_allocations(feature, iterations = 10, &blk)
16+
def bench_allocations(feature, iterations = 10, batch_size = 1000)
1817
puts "GC overhead for #{feature}"
19-
Mysql2Model.establish_connection(:adapter => 'mysql2', :database => 'test')
18+
TestModel.establish_connection(:adapter => 'mysql2', :database => 'test')
2019
GC::Profiler.clear
2120
GC::Profiler.enable
22-
iterations.times{ blk.call }
21+
iterations.times { yield batch_size }
2322
GC::Profiler.report(STDOUT)
2423
GC::Profiler.disable
2524
end
2625

27-
bench_allocations('coercion') do
28-
Mysql2Model.limit(1000).to_a.each{ |r|
29-
r.attributes.keys.each{ |k|
26+
bench_allocations('coercion') do |batch_size|
27+
TestModel.limit(batch_size).to_a.each do |r|
28+
r.attributes.keys.each do |k|
3029
r.send(k.to_sym)
31-
}
32-
}
30+
end
31+
end
3332
end

benchmark/escape.rb

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,32 @@
22
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
33

44
require 'rubygems'
5-
require 'benchmark'
5+
require 'benchmark/ips'
66
require 'mysql'
77
require 'mysql2'
88
require 'do_mysql'
99

10-
def run_escape_benchmarks(str, number_of = 1000)
11-
Benchmark.bmbm do |x|
10+
def run_escape_benchmarks(str)
11+
Benchmark.ips do |x|
1212
mysql = Mysql.new("localhost", "root")
13+
1314
x.report "Mysql #{str.inspect}" do
14-
number_of.times do
15-
mysql.quote str
16-
end
15+
mysql.quote str
1716
end
1817

1918
mysql2 = Mysql2::Client.new(:host => "localhost", :username => "root")
2019
x.report "Mysql2 #{str.inspect}" do
21-
number_of.times do
22-
mysql2.escape str
23-
end
20+
mysql2.escape str
2421
end
2522

2623
do_mysql = DataObjects::Connection.new("mysql://localhost/test")
2724
x.report "do_mysql #{str.inspect}" do
28-
number_of.times do
29-
do_mysql.quote_string str
30-
end
25+
do_mysql.quote_string str
3126
end
27+
28+
x.compare!
3229
end
3330
end
3431

3532
run_escape_benchmarks "abc'def\"ghi\0jkl%mno"
36-
run_escape_benchmarks "clean string"
33+
run_escape_benchmarks "clean string"

benchmark/query_with_mysql_casting.rb

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
33

44
require 'rubygems'
5-
require 'benchmark'
5+
require 'benchmark/ips'
66
require 'mysql'
77
require 'mysql2'
88
require 'do_mysql'
99

10-
number_of = 100
1110
database = 'test'
1211
sql = "SELECT * FROM mysql2_test LIMIT 100"
1312

@@ -17,64 +16,59 @@ class Mysql
1716

1817
def mysql_cast(type, value)
1918
case type
20-
when Mysql::Field::TYPE_NULL
21-
nil
22-
when Mysql::Field::TYPE_TINY, Mysql::Field::TYPE_SHORT, Mysql::Field::TYPE_LONG,
23-
Mysql::Field::TYPE_INT24, Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_YEAR
24-
value.to_i
25-
when Mysql::Field::TYPE_DECIMAL, Mysql::Field::TYPE_NEWDECIMAL
26-
BigDecimal.new(value)
27-
when Mysql::Field::TYPE_DOUBLE, Mysql::Field::TYPE_FLOAT
28-
value.to_f
29-
when Mysql::Field::TYPE_DATE
30-
Date.parse(value)
31-
when Mysql::Field::TYPE_TIME, Mysql::Field::TYPE_DATETIME, Mysql::Field::TYPE_TIMESTAMP
32-
Time.parse(value)
33-
when Mysql::Field::TYPE_BLOB, Mysql::Field::TYPE_BIT, Mysql::Field::TYPE_STRING,
34-
Mysql::Field::TYPE_VAR_STRING, Mysql::Field::TYPE_CHAR, Mysql::Field::TYPE_SET
35-
Mysql::Field::TYPE_ENUM
36-
value
37-
else
38-
value
19+
when Mysql::Field::TYPE_NULL
20+
nil
21+
when Mysql::Field::TYPE_TINY, Mysql::Field::TYPE_SHORT, Mysql::Field::TYPE_LONG,
22+
Mysql::Field::TYPE_INT24, Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_YEAR
23+
value.to_i
24+
when Mysql::Field::TYPE_DECIMAL, Mysql::Field::TYPE_NEWDECIMAL
25+
BigDecimal.new(value)
26+
when Mysql::Field::TYPE_DOUBLE, Mysql::Field::TYPE_FLOAT
27+
value.to_f
28+
when Mysql::Field::TYPE_DATE
29+
Date.parse(value)
30+
when Mysql::Field::TYPE_TIME, Mysql::Field::TYPE_DATETIME, Mysql::Field::TYPE_TIMESTAMP
31+
Time.parse(value)
32+
when Mysql::Field::TYPE_BLOB, Mysql::Field::TYPE_BIT, Mysql::Field::TYPE_STRING,
33+
Mysql::Field::TYPE_VAR_STRING, Mysql::Field::TYPE_CHAR, Mysql::Field::TYPE_SET
34+
Mysql::Field::TYPE_ENUM
35+
value
36+
else
37+
value
3938
end
4039
end
4140

42-
Benchmark.bmbm do |x|
41+
Benchmark.ips do |x|
4342
mysql2 = Mysql2::Client.new(:host => "localhost", :username => "root")
4443
mysql2.query "USE #{database}"
4544
x.report "Mysql2" do
46-
number_of.times do
47-
mysql2_result = mysql2.query sql, :symbolize_keys => true
48-
mysql2_result.each do |res|
49-
# puts res.inspect
50-
end
45+
mysql2_result = mysql2.query sql, :symbolize_keys => true
46+
mysql2_result.each do |res|
47+
# puts res.inspect
5148
end
5249
end
5350

5451
mysql = Mysql.new("localhost", "root")
5552
mysql.query "USE #{database}"
5653
x.report "Mysql" do
57-
number_of.times do
58-
mysql_result = mysql.query sql
59-
fields = mysql_result.fetch_fields
60-
mysql_result.each do |row|
61-
row_hash = {}
62-
row.each_with_index do |f, j|
63-
row_hash[fields[j].name.to_sym] = mysql_cast(fields[j].type, row[j])
64-
end
65-
# puts row_hash.inspect
54+
mysql_result = mysql.query sql
55+
fields = mysql_result.fetch_fields
56+
mysql_result.each do |row|
57+
row_hash = row.each_with_index.each_with_object({}) do |(f, j), hash|
58+
hash[fields[j].name.to_sym] = mysql_cast(fields[j].type, row[j])
6659
end
60+
# puts row_hash.inspect
6761
end
6862
end
6963

7064
do_mysql = DataObjects::Connection.new("mysql://localhost/#{database}")
7165
command = do_mysql.create_command sql
7266
x.report "do_mysql" do
73-
number_of.times do
74-
do_result = command.execute_reader
75-
do_result.each do |res|
76-
# puts res.inspect
77-
end
67+
do_result = command.execute_reader
68+
do_result.each do |res|
69+
# puts res.inspect
7870
end
7971
end
80-
end
72+
73+
x.compare!
74+
end

0 commit comments

Comments
 (0)