-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathperformance.rb
337 lines (265 loc) · 11 KB
/
performance.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", "~> 7.0"
gem "sqlite3"
gem "state_machines", github: "state-machines/state_machines"
gem "state_machines-activerecord", github: "state-machines/state_machines-activerecord"
gem "aasm", github: "aasm/aasm"
gem "enum_machine", github: "corp-gp/enum_machine"
gem "benchmark-ips"
end
require "active_record"
require "benchmark/ips"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
# ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :orders, force: true do |t|
t.string :name
t.string :state
end
end
STATES_IN_TRANSIT = %w[shipped delivered_to_office delivered_to_courier_city].freeze
class OrderEnumMachine < ActiveRecord::Base
self.table_name = :orders
enum_machine :state, %w[
forming confirmed ready_for_collecting collecting collected packed wait_shipment back_picking cancelled shipped
delivered_to_office delivered_to_courier_city part_obtain obtain overdue rejection closed returned merged searched lost
] do
transitions(
[nil] | %w[confirmed ready_for_collecting] => "forming",
[nil] | %w[forming confirmed] => "ready_for_collecting",
[nil] | %w[forming ready_for_collecting] => "confirmed",
"ready_for_collecting" => "collecting",
"collecting" => "collected",
%w[collecting collected] => "packed",
"packed" => "wait_shipment",
%w[forming confirmed ready_for_collecting collecting packed wait_shipment cancelled] => "back_picking",
%w[forming confirmed ready_for_collecting collecting collected packed wait_shipment] => "cancelled",
"wait_shipment" => "shipped",
%w[wait_shipment shipped] => %w[delivered_to_office delivered_to_courier_city],
%w[wait_shipment overdue rejection returned searched lost obtain] | STATES_IN_TRANSIT => "part_obtain",
%w[wait_shipment overdue rejection returned searched lost part_obtain] | STATES_IN_TRANSIT => "obtain",
%w[wait_shipment obtain searched] | STATES_IN_TRANSIT => "overdue",
%w[wait_shipment obtain part_obtain overdue searched] | STATES_IN_TRANSIT => "rejection",
%w[overdue rejection searched lost] => "returned",
%w[part_obtain obtain searched lost] => "closed",
%w[forming confirmed ready_for_collecting packed wait_shipment] => "merged",
%w[wait_shipment shipped part_obtain obtain overdue rejection lost] | STATES_IN_TRANSIT => "searched",
%w[wait_shipment shipped part_obtain obtain overdue rejection searched] | STATES_IN_TRANSIT => "lost",
)
end
end
class OrderAasm < ActiveRecord::Base
include AASM
self.table_name = :orders
aasm :state do # rubocop:disable Metrics/BlockLength
state :default, initial: true
state :forming
state :confirmed
state :ready_for_collecting
state :collecting
state :collected
state :packed
state :wait_shipment
state :back_picking
state :cancelled
state :shipped
state :delivered_to_office
state :delivered_to_courier_city
state :part_obtain
state :obtain
state :overdue
state :rejection
state :closed
state :returned
state :merged
state :searched
state :lost
event :to_forming do
transitions from: %i[default confirmed ready_for_collecting], to: :forming
end
event :to_ready_for_collecting do
transitions from: %i[default forming confirmed], to: :ready_for_collecting
end
event :to_confirmed do
transitions from: %i[default forming ready_for_collecting], to: :confirmed
end
event :to_collecting do
transitions from: :ready_for_collecting, to: :collecting
end
event :to_collected do
transitions from: :collecting, to: :collected
end
event :to_packed do
transitions from: %i[collecting collected], to: :packed
end
event :to_wait_shipment do
transitions from: :packed, to: :wait_shipment
end
event :to_back_picking do
transitions from: %i[forming confirmed ready_for_collecting collecting packed wait_shipment cancelled], to: :back_picking
end
event :to_cancelled do
transitions from: %i[forming confirmed ready_for_collecting collecting collected packed wait_shipment], to: :cancelled
end
event :to_shipped do
transitions from: :wait_shipment, to: :shipped
end
event :to_delivered do
transitions from: %i[wait_shipment shipped], to: %i[delivered_to_office delivered_to_courier_city]
end
event :to_part_obtain do
transitions from: %i[wait_shipment overdue rejection returned searched lost obtain] | STATES_IN_TRANSIT, to: :part_obtain
end
event :to_obtain do
transitions from: %i[wait_shipment overdue rejection returned searched lost part_obtain] | STATES_IN_TRANSIT, to: :obtain
end
event :to_overdue do
transitions from: %i[wait_shipment obtain searched] | STATES_IN_TRANSIT, to: :overdue
end
event :to_rejection do
transitions from: %i[wait_shipment obtain part_obtain overdue searched] | STATES_IN_TRANSIT, to: :rejection
end
event :to_returned do
transitions from: %i[overdue rejection searched lost], to: :returned
end
event :to_closed do
transitions from: %i[part_obtain obtain searched lost], to: :closed
end
event :to_merged do
transitions from: %i[forming confirmed ready_for_collecting packed wait_shipment], to: :merged
end
event :to_searched do
transitions from: %i[wait_shipment shipped part_obtain obtain overdue rejection lost] | STATES_IN_TRANSIT, to: :searched
end
event :to_lost do
transitions from: %i[wait_shipment shipped part_obtain obtain overdue rejection searched] | STATES_IN_TRANSIT, to: :lost
end
end
end
class OrderStateMachines < ActiveRecord::Base
self.table_name = :orders
state_machine :state, initial: nil do
event :to_forming do
transition [nil, "confirmed", "ready_for_collecting"] => "forming"
end
event :to_ready_for_collecting do
transition [nil, "forming", "confirmed"] => "ready_for_collecting"
end
event :to_confirmed do
transition [nil, "forming", "ready_for_collecting"] => "confirmed"
end
event :to_collecting do
transition "ready_for_collecting" => "collecting"
end
event :to_collected do
transition "collecting" => "collected"
end
event :to_packed do
transition %w[collecting collected] => "packed"
end
event :to_wait_shipment do
transition "packed" => "wait_shipment"
end
event :to_back_picking do
transition %w[forming confirmed ready_for_collecting collecting packed wait_shipment cancelled] => "back_picking"
end
event :to_cancelled do
transition %w[forming confirmed ready_for_collecting collecting collected packed wait_shipment] => "cancelled"
end
event :to_shipped do
transition "wait_shipment" => "shipped"
end
event :to_delivered do
transition %w[wait_shipment shipped] => %w[delivered_to_office delivered_to_courier_city]
end
event :to_part_obtain do
transition %w[wait_shipment overdue rejection returned searched lost obtain] | STATES_IN_TRANSIT => "part_obtain"
end
event :to_obtain do
transition %w[wait_shipment overdue rejection returned searched lost part_obtain] | STATES_IN_TRANSIT => "obtain"
end
event :to_overdue do
transition %w[wait_shipment obtain searched] | STATES_IN_TRANSIT => "overdue"
end
event :to_rejection do
transition %w[wait_shipment obtain part_obtain overdue searched] | STATES_IN_TRANSIT => "rejection"
end
event :to_returned do
transition %w[overdue rejection searched lost] => "returned"
end
event :to_closed do
transition %w[part_obtain obtain searched lost] => "closed"
end
event :to_merged do
transition %w[forming confirmed ready_for_collecting packed wait_shipment] => "merged"
end
event :to_searched do
transition %w[wait_shipment shipped part_obtain obtain overdue rejection lost] | STATES_IN_TRANSIT => "searched"
end
event :to_lost do
transition %w[wait_shipment shipped part_obtain obtain overdue rejection searched] | STATES_IN_TRANSIT => "lost"
end
end
end
def pp_title(name, stmt)
"#{name.rjust(15, ' ')} |#{stmt.rjust(50)}"
end
order_attrs = { state: "confirmed", name: "Petrov" }
order_enum_machine = OrderEnumMachine.create!(order_attrs)
order_state_machines = OrderStateMachines.create!(order_attrs)
order_aasm = OrderAasm.create!(order_attrs)
Benchmark.ips(quiet: true) do |x|
x.report(pp_title("enum_machine", "order.state.can_closed?")) do
order_enum_machine.state.can_closed?
end
x.report(pp_title("state_machines", "order.can_to_closed?")) do
order_state_machines.can_to_closed?
end
x.report(pp_title("aasm", "order.may_to_closed?")) do
order_aasm.may_to_closed?
end
x.compare!
end
Benchmark.ips(quiet: true) do |x|
x.report(pp_title("enum_machine", "order.state.forming?")) do
order_enum_machine.state.forming?
end
x.report(pp_title("state_machines", "order.forming?")) do
order_state_machines.forming?
end
x.report(pp_title("aasm", "order.forming?")) do
order_aasm.forming?
end
x.compare!
end
Benchmark.ips(quiet: true) do |x|
x.report(pp_title("enum_machine", "Order::STATE.values")) do
OrderEnumMachine::STATE.values
end
x.report(pp_title("state_machines", "Order.state_machines[:state].states.map(&:value)")) do
OrderStateMachines.state_machines[:state].states.map(&:value)
end
x.report(pp_title("aasm", "Order.aasm(:state).states.map(&:name)")) do
OrderAasm.aasm(:state).states.map(&:name)
end
x.compare!
end
Benchmark.ips(quiet: true) do |x|
x.report(pp_title("enum_machine", 'order.state = "forming" and order.valid?')) do
order = order_enum_machine.dup
order.state = "forming" and order.valid?
end
x.report(pp_title("state_machines", 'order.state_event = "to_forming" and order.valid?')) do
order = order_state_machines.dup
order.state_event = "to_forming" and order.valid?
end
x.report(pp_title("aasm", "order.to_forming")) do
order = order_aasm.dup
order.to_forming
end
x.compare!
end