dm-core 0.9.11 → 0.10.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/.autotest +17 -14
- data/.gitignore +3 -1
- data/FAQ +6 -5
- data/History.txt +5 -50
- data/Manifest.txt +66 -76
- data/QUICKLINKS +1 -1
- data/README.txt +21 -15
- data/Rakefile +6 -7
- data/SPECS +2 -29
- data/TODO +1 -1
- data/deps.rip +2 -0
- data/dm-core.gemspec +11 -15
- data/lib/dm-core.rb +105 -110
- data/lib/dm-core/adapters.rb +135 -16
- data/lib/dm-core/adapters/abstract_adapter.rb +251 -181
- data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
- data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
- data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
- data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
- data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
- data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
- data/lib/dm-core/associations/many_to_many.rb +372 -90
- data/lib/dm-core/associations/many_to_one.rb +220 -73
- data/lib/dm-core/associations/one_to_many.rb +319 -255
- data/lib/dm-core/associations/one_to_one.rb +66 -53
- data/lib/dm-core/associations/relationship.rb +561 -156
- data/lib/dm-core/collection.rb +1101 -379
- data/lib/dm-core/core_ext/kernel.rb +12 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +4 -34
- data/lib/dm-core/migrations.rb +1283 -0
- data/lib/dm-core/model.rb +570 -369
- data/lib/dm-core/model/descendant_set.rb +81 -0
- data/lib/dm-core/model/hook.rb +45 -0
- data/lib/dm-core/model/is.rb +32 -0
- data/lib/dm-core/model/property.rb +247 -0
- data/lib/dm-core/model/relationship.rb +335 -0
- data/lib/dm-core/model/scope.rb +90 -0
- data/lib/dm-core/property.rb +808 -273
- data/lib/dm-core/property_set.rb +141 -98
- data/lib/dm-core/query.rb +1037 -483
- data/lib/dm-core/query/conditions/comparison.rb +872 -0
- data/lib/dm-core/query/conditions/operation.rb +221 -0
- data/lib/dm-core/query/direction.rb +43 -0
- data/lib/dm-core/query/operator.rb +84 -0
- data/lib/dm-core/query/path.rb +138 -0
- data/lib/dm-core/query/sort.rb +45 -0
- data/lib/dm-core/repository.rb +210 -94
- data/lib/dm-core/resource.rb +641 -421
- data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
- data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
- data/lib/dm-core/support/chainable.rb +22 -0
- data/lib/dm-core/support/deprecate.rb +12 -0
- data/lib/dm-core/support/logger.rb +13 -0
- data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
- data/lib/dm-core/transaction.rb +333 -92
- data/lib/dm-core/type.rb +98 -60
- data/lib/dm-core/types/boolean.rb +1 -1
- data/lib/dm-core/types/discriminator.rb +34 -20
- data/lib/dm-core/types/object.rb +7 -4
- data/lib/dm-core/types/paranoid_boolean.rb +11 -9
- data/lib/dm-core/types/paranoid_datetime.rb +11 -9
- data/lib/dm-core/types/serial.rb +3 -3
- data/lib/dm-core/types/text.rb +3 -4
- data/lib/dm-core/version.rb +1 -1
- data/script/performance.rb +102 -109
- data/script/profile.rb +169 -38
- data/spec/lib/adapter_helpers.rb +105 -0
- data/spec/lib/collection_helpers.rb +18 -0
- data/spec/lib/counter_adapter.rb +34 -0
- data/spec/lib/pending_helpers.rb +27 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
- data/spec/public/associations/many_to_many_spec.rb +193 -0
- data/spec/public/associations/many_to_one_spec.rb +73 -0
- data/spec/public/associations/one_to_many_spec.rb +77 -0
- data/spec/public/associations/one_to_one_spec.rb +156 -0
- data/spec/public/collection_spec.rb +65 -0
- data/spec/public/migrations_spec.rb +359 -0
- data/spec/public/model/relationship_spec.rb +924 -0
- data/spec/public/model_spec.rb +159 -0
- data/spec/public/property_spec.rb +829 -0
- data/spec/public/resource_spec.rb +71 -0
- data/spec/public/sel_spec.rb +44 -0
- data/spec/public/setup_spec.rb +145 -0
- data/spec/public/shared/association_collection_shared_spec.rb +317 -0
- data/spec/public/shared/collection_shared_spec.rb +1670 -0
- data/spec/public/shared/finder_shared_spec.rb +1619 -0
- data/spec/public/shared/resource_shared_spec.rb +924 -0
- data/spec/public/shared/sel_shared_spec.rb +112 -0
- data/spec/public/transaction_spec.rb +129 -0
- data/spec/public/types/discriminator_spec.rb +130 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
- data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
- data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
- data/spec/semipublic/associations/relationship_spec.rb +194 -0
- data/spec/semipublic/associations_spec.rb +177 -0
- data/spec/semipublic/collection_spec.rb +142 -0
- data/spec/semipublic/property_spec.rb +61 -0
- data/spec/semipublic/query/conditions_spec.rb +528 -0
- data/spec/semipublic/query/path_spec.rb +443 -0
- data/spec/semipublic/query_spec.rb +2626 -0
- data/spec/semipublic/resource_spec.rb +47 -0
- data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
- data/spec/spec.opts +3 -1
- data/spec/spec_helper.rb +80 -57
- data/tasks/ci.rb +19 -31
- data/tasks/dm.rb +43 -48
- data/tasks/doc.rb +8 -11
- data/tasks/gemspec.rb +5 -5
- data/tasks/hoe.rb +15 -16
- data/tasks/install.rb +8 -10
- metadata +74 -111
- data/lib/dm-core/associations.rb +0 -207
- data/lib/dm-core/associations/relationship_chain.rb +0 -81
- data/lib/dm-core/auto_migrations.rb +0 -105
- data/lib/dm-core/dependency_queue.rb +0 -32
- data/lib/dm-core/hook.rb +0 -11
- data/lib/dm-core/is.rb +0 -16
- data/lib/dm-core/logger.rb +0 -232
- data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
- data/lib/dm-core/migrator.rb +0 -29
- data/lib/dm-core/scope.rb +0 -58
- data/lib/dm-core/support.rb +0 -7
- data/lib/dm-core/support/array.rb +0 -13
- data/lib/dm-core/support/assertions.rb +0 -8
- data/lib/dm-core/support/errors.rb +0 -23
- data/lib/dm-core/support/kernel.rb +0 -11
- data/lib/dm-core/support/symbol.rb +0 -41
- data/lib/dm-core/type_map.rb +0 -80
- data/lib/dm-core/types.rb +0 -19
- data/script/all +0 -4
- data/spec/integration/association_spec.rb +0 -1382
- data/spec/integration/association_through_spec.rb +0 -203
- data/spec/integration/associations/many_to_many_spec.rb +0 -449
- data/spec/integration/associations/many_to_one_spec.rb +0 -163
- data/spec/integration/associations/one_to_many_spec.rb +0 -188
- data/spec/integration/auto_migrations_spec.rb +0 -413
- data/spec/integration/collection_spec.rb +0 -1073
- data/spec/integration/data_objects_adapter_spec.rb +0 -32
- data/spec/integration/dependency_queue_spec.rb +0 -46
- data/spec/integration/model_spec.rb +0 -197
- data/spec/integration/mysql_adapter_spec.rb +0 -85
- data/spec/integration/postgres_adapter_spec.rb +0 -731
- data/spec/integration/property_spec.rb +0 -253
- data/spec/integration/query_spec.rb +0 -514
- data/spec/integration/repository_spec.rb +0 -61
- data/spec/integration/resource_spec.rb +0 -513
- data/spec/integration/sqlite3_adapter_spec.rb +0 -352
- data/spec/integration/sti_spec.rb +0 -273
- data/spec/integration/strategic_eager_loading_spec.rb +0 -156
- data/spec/integration/transaction_spec.rb +0 -75
- data/spec/integration/type_spec.rb +0 -275
- data/spec/lib/logging_helper.rb +0 -18
- data/spec/lib/mock_adapter.rb +0 -27
- data/spec/lib/model_loader.rb +0 -100
- data/spec/lib/publicize_methods.rb +0 -28
- data/spec/models/content.rb +0 -16
- data/spec/models/vehicles.rb +0 -34
- data/spec/models/zoo.rb +0 -48
- data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
- data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
- data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
- data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
- data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
- data/spec/unit/associations/many_to_many_spec.rb +0 -32
- data/spec/unit/associations/many_to_one_spec.rb +0 -159
- data/spec/unit/associations/one_to_many_spec.rb +0 -393
- data/spec/unit/associations/one_to_one_spec.rb +0 -7
- data/spec/unit/associations/relationship_spec.rb +0 -71
- data/spec/unit/associations_spec.rb +0 -242
- data/spec/unit/auto_migrations_spec.rb +0 -111
- data/spec/unit/collection_spec.rb +0 -182
- data/spec/unit/data_mapper_spec.rb +0 -35
- data/spec/unit/identity_map_spec.rb +0 -126
- data/spec/unit/is_spec.rb +0 -80
- data/spec/unit/migrator_spec.rb +0 -33
- data/spec/unit/model_spec.rb +0 -321
- data/spec/unit/naming_conventions_spec.rb +0 -36
- data/spec/unit/property_set_spec.rb +0 -90
- data/spec/unit/property_spec.rb +0 -753
- data/spec/unit/query_spec.rb +0 -571
- data/spec/unit/repository_spec.rb +0 -93
- data/spec/unit/resource_spec.rb +0 -649
- data/spec/unit/scope_spec.rb +0 -142
- data/spec/unit/transaction_spec.rb +0 -493
- data/spec/unit/type_map_spec.rb +0 -114
- data/spec/unit/type_spec.rb +0 -119
data/lib/dm-core/version.rb
CHANGED
data/script/performance.rb
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core')
|
|
4
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core', 'version')
|
|
1
|
+
#!/usr/bin/env ruby -KU
|
|
5
2
|
|
|
6
3
|
require 'ftools'
|
|
7
4
|
require 'rubygems'
|
|
8
5
|
|
|
9
|
-
gem '
|
|
10
|
-
|
|
6
|
+
gem 'activerecord', '~>2.3.2'
|
|
7
|
+
gem 'addressable', '~>2.0'
|
|
8
|
+
gem 'faker', '~>0.3.1'
|
|
9
|
+
gem 'rbench', '~>0.2.3'
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
require 'active_record'
|
|
12
|
+
require 'addressable/uri'
|
|
13
13
|
require 'faker'
|
|
14
|
+
require 'rbench'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
require 'active_record'
|
|
16
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core'))
|
|
17
17
|
|
|
18
18
|
socket_file = Pathname.glob(%w[
|
|
19
19
|
/opt/local/var/run/mysql5/mysqld.sock
|
|
@@ -29,7 +29,7 @@ configuration_options = {
|
|
|
29
29
|
:adapter => 'mysql',
|
|
30
30
|
:username => 'root',
|
|
31
31
|
:password => '',
|
|
32
|
-
:database => '
|
|
32
|
+
:database => 'dm_core_test',
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
configuration_options[:socket] = socket_file unless socket_file.nil?
|
|
@@ -38,12 +38,12 @@ log_dir = DataMapper.root / 'log'
|
|
|
38
38
|
log_dir.mkdir unless log_dir.directory?
|
|
39
39
|
|
|
40
40
|
DataMapper::Logger.new(log_dir / 'dm.log', :off)
|
|
41
|
-
adapter = DataMapper.setup(:default, "mysql://root@localhost/
|
|
41
|
+
adapter = DataMapper.setup(:default, "mysql://root@localhost/dm_core_test?socket=#{socket_file}")
|
|
42
42
|
|
|
43
43
|
if configuration_options[:adapter]
|
|
44
|
-
sqlfile
|
|
45
|
-
mysql_bin
|
|
46
|
-
mysqldump_bin = %w[mysqldump mysqldump5].select{|bin| `which #{bin}`.length > 0 }
|
|
44
|
+
sqlfile = File.join(File.dirname(__FILE__), '..', 'tmp', 'performance.sql')
|
|
45
|
+
mysql_bin = %w[ mysql mysql5 ].select { |bin| `which #{bin}`.length > 0 }
|
|
46
|
+
mysqldump_bin = %w[ mysqldump mysqldump5 ].select { |bin| `which #{bin}`.length > 0 }
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
ActiveRecord::Base.logger = Logger.new(log_dir / 'ar.log')
|
|
@@ -61,46 +61,45 @@ class ARUser < ActiveRecord::Base #:nodoc:
|
|
|
61
61
|
set_table_name 'users'
|
|
62
62
|
|
|
63
63
|
has_many :exhibits, :foreign_key => 'user_id'
|
|
64
|
-
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
ARExhibit.find_by_sql('SELECT 1')
|
|
68
67
|
|
|
69
|
-
class
|
|
68
|
+
class User
|
|
70
69
|
include DataMapper::Resource
|
|
71
70
|
|
|
72
71
|
property :id, Serial
|
|
73
72
|
property :name, String
|
|
74
|
-
property :
|
|
75
|
-
property :
|
|
76
|
-
property :notes, Text, :lazy => true
|
|
73
|
+
property :email, String
|
|
74
|
+
property :about, Text, :lazy => false
|
|
77
75
|
property :created_on, Date
|
|
78
|
-
|
|
79
|
-
belongs_to :user
|
|
80
|
-
# property :updated_at, DateTime
|
|
81
76
|
end
|
|
82
77
|
|
|
83
|
-
class
|
|
78
|
+
class Exhibit
|
|
84
79
|
include DataMapper::Resource
|
|
85
80
|
|
|
86
|
-
property :id,
|
|
87
|
-
property :name,
|
|
88
|
-
property :
|
|
89
|
-
property :
|
|
81
|
+
property :id, Serial
|
|
82
|
+
property :name, String
|
|
83
|
+
property :zoo_id, Integer
|
|
84
|
+
property :user_id, Integer
|
|
85
|
+
property :notes, Text, :lazy => false
|
|
90
86
|
property :created_on, Date
|
|
91
87
|
|
|
88
|
+
belongs_to :user
|
|
92
89
|
end
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
DataMapper.auto_migrate!
|
|
92
|
+
|
|
93
|
+
def touch_attributes(*exhibits)
|
|
94
|
+
exhibits.flatten.each do |exhibit|
|
|
96
95
|
exhibit.id
|
|
97
96
|
exhibit.name
|
|
98
97
|
exhibit.created_on
|
|
99
98
|
end
|
|
100
99
|
end
|
|
101
100
|
|
|
102
|
-
touch_relationships
|
|
103
|
-
|
|
101
|
+
def touch_relationships(*exhibits)
|
|
102
|
+
exhibits.flatten.each do |exhibit|
|
|
104
103
|
exhibit.id
|
|
105
104
|
exhibit.name
|
|
106
105
|
exhibit.created_on
|
|
@@ -108,7 +107,6 @@ touch_relationships = lambda do |exhibits|
|
|
|
108
107
|
end
|
|
109
108
|
end
|
|
110
109
|
|
|
111
|
-
|
|
112
110
|
c = configuration_options
|
|
113
111
|
|
|
114
112
|
if sqlfile && File.exists?(sqlfile)
|
|
@@ -116,14 +114,7 @@ if sqlfile && File.exists?(sqlfile)
|
|
|
116
114
|
#adapter.execute("LOAD DATA LOCAL INFILE '#{sqlfile}' INTO TABLE exhibits")
|
|
117
115
|
`#{mysql_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} < #{sqlfile}`
|
|
118
116
|
else
|
|
119
|
-
|
|
120
|
-
puts "Generating data for benchmarking..."
|
|
121
|
-
|
|
122
|
-
User.auto_migrate!
|
|
123
|
-
Exhibit.auto_migrate!
|
|
124
|
-
|
|
125
|
-
users = []
|
|
126
|
-
exhibits = []
|
|
117
|
+
puts 'Generating data for benchmarking...'
|
|
127
118
|
|
|
128
119
|
# pre-compute the insert statements and fake data compilation,
|
|
129
120
|
# so the benchmarks below show the actual runtime for the execute
|
|
@@ -131,35 +122,30 @@ else
|
|
|
131
122
|
|
|
132
123
|
# Using the same paragraph for all exhibits because it is very slow
|
|
133
124
|
# to generate unique paragraphs for all exhibits.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
125
|
+
notes = Faker::Lorem.paragraphs.join($/)
|
|
126
|
+
today = Date.today
|
|
127
|
+
|
|
128
|
+
puts 'Inserting 10,000 users and exhibits...'
|
|
129
|
+
10_000.times do
|
|
130
|
+
user = User.create(
|
|
131
|
+
:created_on => today,
|
|
132
|
+
:name => Faker::Name.name,
|
|
133
|
+
:email => Faker::Internet.email
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
Exhibit.create(
|
|
137
|
+
:created_on => today,
|
|
138
|
+
:name => Faker::Company.name,
|
|
139
|
+
:user => user,
|
|
140
|
+
:notes => notes,
|
|
141
|
+
:zoo_id => rand(10).ceil
|
|
142
|
+
)
|
|
152
143
|
end
|
|
153
144
|
|
|
154
|
-
puts "Inserting 10,000 users..."
|
|
155
|
-
10_000.times { |i| adapter.execute(*users.at(i)) }
|
|
156
|
-
puts "Inserting 10,000 exhibits..."
|
|
157
|
-
10_000.times { |i| adapter.execute(*exhibits.at(i)) }
|
|
158
|
-
|
|
159
145
|
if sqlfile
|
|
160
146
|
answer = nil
|
|
161
147
|
until answer && answer[/^$|y|yes|n|no/]
|
|
162
|
-
print(
|
|
148
|
+
print('Would you like to dump data into tmp/performance.sql (for faster setup)? [Yn]');
|
|
163
149
|
STDOUT.flush
|
|
164
150
|
answer = gets
|
|
165
151
|
end
|
|
@@ -171,13 +157,12 @@ else
|
|
|
171
157
|
puts "File saved\n"
|
|
172
158
|
end
|
|
173
159
|
end
|
|
174
|
-
|
|
175
160
|
end
|
|
176
161
|
|
|
177
|
-
TIMES = ENV
|
|
162
|
+
TIMES = ENV.key?('x') ? ENV['x'].to_i : 10_000
|
|
178
163
|
|
|
179
|
-
puts
|
|
180
|
-
puts
|
|
164
|
+
puts 'You can specify how many times you want to run the benchmarks with rake:perf x=(number)'
|
|
165
|
+
puts 'Some tasks will be run 10 and 1000 times less than (number)'
|
|
181
166
|
puts "Benchmarks will now run #{TIMES} times"
|
|
182
167
|
# Inform about slow benchmark
|
|
183
168
|
# answer = nil
|
|
@@ -193,90 +178,98 @@ puts "Benchmarks will now run #{TIMES} times"
|
|
|
193
178
|
RBench.run(TIMES) do
|
|
194
179
|
|
|
195
180
|
column :times
|
|
196
|
-
column :ar, :title =>
|
|
181
|
+
column :ar, :title => 'AR 2.3.2'
|
|
197
182
|
column :dm, :title => "DM #{DataMapper::VERSION}"
|
|
198
|
-
column :diff, :compare => [:ar
|
|
183
|
+
column :diff, :compare => [:ar, :dm]
|
|
184
|
+
|
|
185
|
+
report 'Model#id', (TIMES * 100).ceil do
|
|
186
|
+
ar_obj = ARExhibit.find(1)
|
|
187
|
+
dm_obj = Exhibit.get(1)
|
|
188
|
+
|
|
189
|
+
ar { ar_obj.id }
|
|
190
|
+
dm { dm_obj.id }
|
|
191
|
+
end
|
|
199
192
|
|
|
200
|
-
report
|
|
193
|
+
report 'Model.new (instantiation)' do
|
|
201
194
|
ar { ARExhibit.new }
|
|
202
195
|
dm { Exhibit.new }
|
|
203
196
|
end
|
|
204
197
|
|
|
205
|
-
report
|
|
206
|
-
attrs = {:name => 'sam', :zoo_id => 1}
|
|
198
|
+
report 'Model.new (setting attributes)' do
|
|
199
|
+
attrs = { :name => 'sam', :zoo_id => 1 }
|
|
207
200
|
ar { ARExhibit.new(attrs) }
|
|
208
201
|
dm { Exhibit.new(attrs) }
|
|
209
202
|
end
|
|
210
203
|
|
|
211
|
-
report
|
|
212
|
-
ActiveRecord::Base.uncached { ar { touch_attributes
|
|
213
|
-
dm { touch_attributes
|
|
204
|
+
report 'Model.get specific (not cached)' do
|
|
205
|
+
ActiveRecord::Base.uncached { ar { touch_attributes(ARExhibit.find(1)) } }
|
|
206
|
+
dm { touch_attributes(Exhibit.get(1)) }
|
|
214
207
|
end
|
|
215
208
|
|
|
216
|
-
report
|
|
217
|
-
ActiveRecord::Base.cache
|
|
218
|
-
Exhibit.repository(:default) { dm { touch_attributes
|
|
209
|
+
report 'Model.get specific (cached)' do
|
|
210
|
+
ActiveRecord::Base.cache { ar { touch_attributes(ARExhibit.find(1)) } }
|
|
211
|
+
Exhibit.repository(:default) { dm { touch_attributes(Exhibit.get(1)) } }
|
|
219
212
|
end
|
|
220
213
|
|
|
221
|
-
report
|
|
222
|
-
ar { touch_attributes
|
|
223
|
-
dm { touch_attributes
|
|
214
|
+
report 'Model.first' do
|
|
215
|
+
ar { touch_attributes(ARExhibit.first) }
|
|
216
|
+
dm { touch_attributes(Exhibit.first) }
|
|
224
217
|
end
|
|
225
218
|
|
|
226
|
-
report
|
|
227
|
-
ar { touch_attributes
|
|
228
|
-
dm { touch_attributes
|
|
219
|
+
report 'Model.all limit(100)', (TIMES / 10).ceil do
|
|
220
|
+
ar { touch_attributes(ARExhibit.find(:all, :limit => 100)) }
|
|
221
|
+
dm { touch_attributes(Exhibit.all(:limit => 100)) }
|
|
229
222
|
end
|
|
230
223
|
|
|
231
|
-
report
|
|
232
|
-
ar { touch_relationships
|
|
233
|
-
dm { touch_relationships
|
|
224
|
+
report 'Model.all limit(100) with relationship', (TIMES / 10).ceil do
|
|
225
|
+
ar { touch_relationships(ARExhibit.all(:limit => 100, :include => [ :user ])) }
|
|
226
|
+
dm { touch_relationships(Exhibit.all(:limit => 100)) }
|
|
234
227
|
end
|
|
235
228
|
|
|
236
|
-
report
|
|
237
|
-
ar { touch_attributes
|
|
238
|
-
dm { touch_attributes
|
|
229
|
+
report 'Model.all limit(10,000)', (TIMES / 1000).ceil do
|
|
230
|
+
ar { touch_attributes(ARExhibit.find(:all, :limit => 10_000)) }
|
|
231
|
+
dm { touch_attributes(Exhibit.all(:limit => 10_000)) }
|
|
239
232
|
end
|
|
240
233
|
|
|
241
|
-
|
|
234
|
+
exhibit = {
|
|
242
235
|
:name => Faker::Company.name,
|
|
243
236
|
:zoo_id => rand(10).ceil,
|
|
244
237
|
:notes => Faker::Lorem.paragraphs.join($/),
|
|
245
238
|
:created_on => Date.today
|
|
246
239
|
}
|
|
247
240
|
|
|
248
|
-
report
|
|
249
|
-
ar { ARExhibit.create(
|
|
250
|
-
dm { Exhibit.create(
|
|
241
|
+
report 'Model.create' do
|
|
242
|
+
ar { ARExhibit.create(exhibit) }
|
|
243
|
+
dm { Exhibit.create(exhibit) }
|
|
251
244
|
end
|
|
252
245
|
|
|
253
|
-
report
|
|
254
|
-
attrs_first = {:name => 'sam', :zoo_id => 1}
|
|
255
|
-
attrs_second = {:name => 'tom', :zoo_id => 1}
|
|
256
|
-
ar {
|
|
257
|
-
dm {
|
|
246
|
+
report 'Resource#attributes=' do
|
|
247
|
+
attrs_first = { :name => 'sam', :zoo_id => 1 }
|
|
248
|
+
attrs_second = { :name => 'tom', :zoo_id => 1 }
|
|
249
|
+
ar { exhibit = ARExhibit.new(attrs_first); exhibit.attributes = attrs_second }
|
|
250
|
+
dm { exhibit = Exhibit.new(attrs_first); exhibit.attributes = attrs_second }
|
|
258
251
|
end
|
|
259
252
|
|
|
260
|
-
report
|
|
261
|
-
ar {
|
|
262
|
-
dm {
|
|
253
|
+
report 'Resource#update' do
|
|
254
|
+
ar { ARExhibit.find(1).update_attributes(:name => 'bob') }
|
|
255
|
+
dm { Exhibit.get(1).update(:name => 'bob') }
|
|
263
256
|
end
|
|
264
257
|
|
|
265
|
-
report
|
|
258
|
+
report 'Resource#destroy' do
|
|
266
259
|
ar { ARExhibit.first.destroy }
|
|
267
260
|
dm { Exhibit.first.destroy }
|
|
268
261
|
end
|
|
269
262
|
|
|
270
|
-
report
|
|
263
|
+
report 'Model.transaction' do
|
|
271
264
|
ar { ARExhibit.transaction { ARExhibit.new } }
|
|
272
265
|
dm { Exhibit.transaction { Exhibit.new } }
|
|
273
266
|
end
|
|
274
267
|
|
|
275
|
-
summary
|
|
268
|
+
summary 'Total'
|
|
276
269
|
end
|
|
277
270
|
|
|
278
|
-
connection = adapter.send(:
|
|
279
|
-
command = connection.create_command(
|
|
280
|
-
command = connection.create_command(
|
|
271
|
+
connection = adapter.send(:open_connection)
|
|
272
|
+
command = connection.create_command('DROP TABLE exhibits')
|
|
273
|
+
command = connection.create_command('DROP TABLE users')
|
|
281
274
|
command.execute_non_query rescue nil
|
|
282
275
|
connection.close
|
data/script/profile.rb
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core')
|
|
1
|
+
#!/usr/bin/env ruby -KU
|
|
4
2
|
|
|
3
|
+
require 'ftools'
|
|
5
4
|
require 'rubygems'
|
|
6
5
|
|
|
7
|
-
gem '
|
|
8
|
-
|
|
6
|
+
gem 'addressable', '~>2.0'
|
|
7
|
+
gem 'faker', '~>0.3.1'
|
|
8
|
+
gem 'ruby-prof', '~>0.7.3'
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
require 'addressable/uri'
|
|
11
11
|
require 'faker'
|
|
12
|
+
require 'ruby-prof'
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core'))
|
|
15
|
+
|
|
16
|
+
TEXT_OUTPUT = DataMapper.root / 'profile_results.txt'
|
|
17
|
+
HTML_OUTPUT = DataMapper.root / 'profile_results.html'
|
|
18
|
+
CALL_OUTPUT = DataMapper.root / 'profile_results.prof'
|
|
15
19
|
|
|
16
20
|
SOCKET_FILE = Pathname.glob(%w[
|
|
17
21
|
/opt/local/var/run/mysql5/mysqld.sock
|
|
@@ -21,8 +25,33 @@ SOCKET_FILE = Pathname.glob(%w[
|
|
|
21
25
|
/var/run/mysqld/mysqld.sock
|
|
22
26
|
]).find { |path| path.socket? }
|
|
23
27
|
|
|
28
|
+
configuration_options = {
|
|
29
|
+
:adapter => 'mysql',
|
|
30
|
+
:database => 'dm_core_test',
|
|
31
|
+
:host => 'localhost',
|
|
32
|
+
:username => 'root',
|
|
33
|
+
:password => '',
|
|
34
|
+
:socket => SOCKET_FILE,
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
DataMapper::Logger.new(DataMapper.root / 'log' / 'dm.log', :debug)
|
|
25
|
-
DataMapper.setup(:default,
|
|
38
|
+
adapter = DataMapper.setup(:default, configuration_options)
|
|
39
|
+
|
|
40
|
+
if configuration_options[:adapter]
|
|
41
|
+
sqlfile = File.join(File.dirname(__FILE__), '..', 'tmp', 'performance.sql')
|
|
42
|
+
mysql_bin = %w[ mysql mysql5 ].select { |bin| `which #{bin}`.length > 0 }
|
|
43
|
+
mysqldump_bin = %w[ mysqldump mysqldump5 ].select { |bin| `which #{bin}`.length > 0 }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class User
|
|
47
|
+
include DataMapper::Resource
|
|
48
|
+
|
|
49
|
+
property :id, Serial
|
|
50
|
+
property :name, String
|
|
51
|
+
property :email, String
|
|
52
|
+
property :about, Text, :lazy => false
|
|
53
|
+
property :created_on, Date
|
|
54
|
+
end
|
|
26
55
|
|
|
27
56
|
class Exhibit
|
|
28
57
|
include DataMapper::Resource
|
|
@@ -30,58 +59,160 @@ class Exhibit
|
|
|
30
59
|
property :id, Serial
|
|
31
60
|
property :name, String
|
|
32
61
|
property :zoo_id, Integer
|
|
33
|
-
property :
|
|
62
|
+
property :user_id, Integer
|
|
63
|
+
property :notes, Text, :lazy => false
|
|
34
64
|
property :created_on, Date
|
|
35
|
-
# property :updated_at, DateTime
|
|
36
65
|
|
|
37
|
-
|
|
38
|
-
|
|
66
|
+
belongs_to :user
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
DataMapper.auto_migrate!
|
|
70
|
+
|
|
71
|
+
def touch_attributes(*exhibits)
|
|
72
|
+
exhibits.flatten.each do |exhibit|
|
|
73
|
+
exhibit.id
|
|
74
|
+
exhibit.name
|
|
75
|
+
exhibit.created_on
|
|
76
|
+
end
|
|
39
77
|
end
|
|
40
78
|
|
|
41
|
-
|
|
42
|
-
|
|
79
|
+
def touch_relationships(*exhibits)
|
|
80
|
+
exhibits.flatten.each do |exhibit|
|
|
43
81
|
exhibit.id
|
|
44
82
|
exhibit.name
|
|
45
83
|
exhibit.created_on
|
|
46
|
-
exhibit.
|
|
84
|
+
exhibit.user
|
|
47
85
|
end
|
|
48
86
|
end
|
|
49
87
|
|
|
50
88
|
# RubyProf, making profiling Ruby pretty since 1899!
|
|
51
89
|
def profile(&b)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
results = RubyProf.profile(&b)
|
|
91
|
+
|
|
92
|
+
TEXT_OUTPUT.open('w+') do |file|
|
|
93
|
+
RubyProf::FlatPrinter.new(results).print(file)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
HTML_OUTPUT.open('w+') do |file|
|
|
97
|
+
RubyProf::GraphHtmlPrinter.new(results).print(file)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
CALL_OUTPUT.open('w+') do |file|
|
|
101
|
+
RubyProf::CallTreePrinter.new(results).print(file)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
c = configuration_options
|
|
106
|
+
|
|
107
|
+
if sqlfile && File.exists?(sqlfile)
|
|
108
|
+
puts "Found data-file. Importing from #{sqlfile}"
|
|
109
|
+
#adapter.execute("LOAD DATA LOCAL INFILE '#{sqlfile}' INTO TABLE exhibits")
|
|
110
|
+
`#{mysql_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} < #{sqlfile}`
|
|
111
|
+
else
|
|
112
|
+
puts 'Generating data for benchmarking...'
|
|
113
|
+
|
|
114
|
+
# pre-compute the insert statements and fake data compilation,
|
|
115
|
+
# so the benchmarks below show the actual runtime for the execute
|
|
116
|
+
# method, minus the setup steps
|
|
117
|
+
|
|
118
|
+
# Using the same paragraph for all exhibits because it is very slow
|
|
119
|
+
# to generate unique paragraphs for all exhibits.
|
|
120
|
+
notes = Faker::Lorem.paragraphs.join($/)
|
|
121
|
+
today = Date.today
|
|
122
|
+
|
|
123
|
+
puts 'Inserting 10,000 users and exhibits...'
|
|
124
|
+
10_000.times do
|
|
125
|
+
user = User.create(
|
|
126
|
+
:created_on => today,
|
|
127
|
+
:name => Faker::Name.name,
|
|
128
|
+
:email => Faker::Internet.email
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
Exhibit.create(
|
|
132
|
+
:created_on => today,
|
|
133
|
+
:name => Faker::Company.name,
|
|
134
|
+
:user => user,
|
|
135
|
+
:notes => notes,
|
|
136
|
+
:zoo_id => rand(10).ceil
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
if sqlfile
|
|
141
|
+
answer = nil
|
|
142
|
+
until answer && answer[/^$|y|yes|n|no/]
|
|
143
|
+
print('Would you like to dump data into tmp/performance.sql (for faster setup)? [Yn]');
|
|
144
|
+
STDOUT.flush
|
|
145
|
+
answer = gets
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if answer[/^$|y|yes/]
|
|
149
|
+
File.makedirs(File.dirname(sqlfile))
|
|
150
|
+
#adapter.execute("SELECT * INTO OUTFILE '#{sqlfile}' FROM exhibits;")
|
|
151
|
+
`#{mysqldump_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} exhibits users > #{sqlfile}`
|
|
152
|
+
puts "File saved\n"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
56
155
|
end
|
|
57
156
|
|
|
157
|
+
TIMES = 10_000
|
|
158
|
+
|
|
159
|
+
exhibits = Exhibit.all.to_a
|
|
160
|
+
|
|
58
161
|
profile do
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# 10_000.times { touch_attributes[Exhibit.get(1)] }
|
|
63
|
-
# end
|
|
162
|
+
# dm_obj = Exhibit.get(1)
|
|
163
|
+
# puts 'Model#id'
|
|
164
|
+
# (TIMES * 100).times { dm_obj.id }
|
|
64
165
|
#
|
|
65
|
-
#
|
|
166
|
+
# puts 'Model.new (instantiation)'
|
|
167
|
+
# TIMES.times { Exhibit.new }
|
|
66
168
|
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# end
|
|
169
|
+
# puts 'Model.new (setting attributes)'
|
|
170
|
+
# TIMES.times { Exhibit.new(:name => 'sam', :zoo_id => 1) }
|
|
70
171
|
#
|
|
71
|
-
#
|
|
172
|
+
# puts 'Model.get specific (not cached)'
|
|
173
|
+
# TIMES.times { touch_attributes(Exhibit.get(1)) }
|
|
72
174
|
#
|
|
175
|
+
# puts 'Model.get specific (cached)'
|
|
73
176
|
# repository(:default) do
|
|
74
|
-
#
|
|
177
|
+
# TIMES.times { touch_attributes(Exhibit.get(1)) }
|
|
75
178
|
# end
|
|
76
179
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
:zoo_id => rand(10).ceil,
|
|
80
|
-
:notes => Faker::Lorem.paragraphs.join($/),
|
|
81
|
-
:created_on => Date.today
|
|
82
|
-
}
|
|
180
|
+
puts 'Model.first'
|
|
181
|
+
TIMES.times { touch_attributes(Exhibit.first) }
|
|
83
182
|
|
|
84
|
-
|
|
183
|
+
# puts 'Model.all limit(100)'
|
|
184
|
+
# (TIMES / 10).ceil.times { touch_attributes(Exhibit.all(:limit => 100)) }
|
|
185
|
+
#
|
|
186
|
+
# puts 'Model.all limit(100) with relationship'
|
|
187
|
+
# (TIMES / 10).ceil.times { touch_relationships(Exhibit.all(:limit => 100)) }
|
|
188
|
+
#
|
|
189
|
+
# puts 'Model.all limit(10,000)'
|
|
190
|
+
# (TIMES / 1000).ceil { touch_attributes(Exhibit.all(:limit => 10_000)) }
|
|
191
|
+
#
|
|
192
|
+
# exhibit = {
|
|
193
|
+
# :name => Faker::Company.name,
|
|
194
|
+
# :zoo_id => rand(10).ceil,
|
|
195
|
+
# :notes => Faker::Lorem.paragraphs.join($/),
|
|
196
|
+
# :created_on => Date.today
|
|
197
|
+
# }
|
|
198
|
+
#
|
|
199
|
+
# puts 'Model.create'
|
|
200
|
+
# TIMES.times { Exhibit.create(exhibit) }
|
|
201
|
+
#
|
|
202
|
+
# attrs_first = { :name => 'sam', :zoo_id => 1 }
|
|
203
|
+
# attrs_second = { :name => 'tom', :zoo_id => 1 }
|
|
204
|
+
#
|
|
205
|
+
# puts 'Resource#attributes='
|
|
206
|
+
# TIMES.times { exhibit = Exhibit.new(attrs_first); exhibit.attributes = attrs_second }
|
|
207
|
+
#
|
|
208
|
+
# puts 'Resource#update'
|
|
209
|
+
# TIMES.times { |index| exhibit = exhibits[index]; exhibit.name = 'bob'; exhibit.save }
|
|
210
|
+
#
|
|
211
|
+
# puts 'Resource#destroy'
|
|
212
|
+
# TIMES.times { |index| exhibits[index].destroy }
|
|
213
|
+
#
|
|
214
|
+
# puts 'Model.transaction'
|
|
215
|
+
# TIMES.times { Exhibit.transaction { Exhibit.new } }
|
|
85
216
|
end
|
|
86
217
|
|
|
87
218
|
puts "Done!"
|