knapsack 3.0.0 → 3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/knapsack/distributors/report_distributor.rb +24 -45
- data/lib/knapsack/version.rb +1 -1
- data/spec/knapsack/distributors/report_distributor_spec.rb +87 -11
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d27f3b6225aefe7c7a2ff1a4071961e65c5e087a5256d7294bca73398ce2c997
|
4
|
+
data.tar.gz: 38f324e2d35800297e8c071caef06100688d1e1617bb8f3339076b9c9c1de828
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d635a77401b2d65914edab41f2ac726901d38b937869fb408cc2548d6547114a0d968c06a8c9adfe4f5a2c3d3d7c11bea5bb0c8161d706e17870ea3682b5be0
|
7
|
+
data.tar.gz: b5aa3601e1d7cbdffdfa33a4de64d562782c74371f9e3c58b0754b262a86554c8320e7fb0aff1c84cd6e05755b66c29b61b87f83ffb3a44d4f06eb9c38c8dfd6
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
* TODO
|
4
4
|
|
5
|
+
### 3.1.0
|
6
|
+
|
7
|
+
* Sorting Algorithm: round robin to least connections
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack/pull/99
|
10
|
+
|
11
|
+
https://github.com/KnapsackPro/knapsack/compare/v3.0.0...v3.1.0
|
12
|
+
|
5
13
|
### 3.0.0
|
6
14
|
|
7
15
|
* __(breaking change)__ Require minimum Ruby 2.2 version
|
@@ -2,7 +2,7 @@ module Knapsack
|
|
2
2
|
module Distributors
|
3
3
|
class ReportDistributor < BaseDistributor
|
4
4
|
def sorted_report
|
5
|
-
@sorted_report ||= report.sort_by { |
|
5
|
+
@sorted_report ||= report.sort_by { |_test_path, time| -time }
|
6
6
|
end
|
7
7
|
|
8
8
|
def sorted_report_with_existing_tests
|
@@ -10,7 +10,7 @@ module Knapsack
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def total_time_execution
|
13
|
-
@total_time_execution ||= sorted_report_with_existing_tests.map
|
13
|
+
@total_time_execution ||= sorted_report_with_existing_tests.map { |_test_path, time| time }.reduce(0, :+).to_f
|
14
14
|
end
|
15
15
|
|
16
16
|
def node_time_execution
|
@@ -20,73 +20,52 @@ module Knapsack
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def post_assign_test_files_to_node
|
23
|
-
|
24
|
-
assign_remaining_test_files
|
23
|
+
assign_test_files
|
25
24
|
sort_assigned_test_files
|
26
25
|
end
|
27
26
|
|
28
27
|
def sort_assigned_test_files
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
node_tests.map do |node|
|
29
|
+
node[:test_files_with_time]
|
30
|
+
.sort_by! { |file_name, _time| file_name }
|
31
|
+
.reverse!
|
32
|
+
.sort_by! { |_file_name, time| time }
|
33
|
+
.reverse!
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
37
|
def post_tests_for_node(node_index)
|
39
38
|
node_test = node_tests[node_index]
|
40
39
|
return unless node_test
|
41
|
-
node_test[:test_files_with_time].map
|
40
|
+
node_test[:test_files_with_time].map { |file_name, _time| file_name }
|
42
41
|
end
|
43
42
|
|
44
43
|
def default_node_tests
|
45
|
-
@node_tests =
|
46
|
-
|
47
|
-
@node_tests << {
|
44
|
+
@node_tests = Array.new(ci_node_total) do |index|
|
45
|
+
{
|
48
46
|
node_index: index,
|
49
47
|
time_left: node_time_execution,
|
50
|
-
test_files_with_time: []
|
48
|
+
test_files_with_time: [],
|
49
|
+
weight: 0
|
51
50
|
}
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
sorted_report_with_existing_tests.each do |test_file_with_time|
|
59
|
-
assign_slow_test_file(node_index, test_file_with_time)
|
60
|
-
node_index += 1
|
61
|
-
node_index %= ci_node_total
|
62
|
-
end
|
63
|
-
end
|
54
|
+
def assign_test_files
|
55
|
+
sorted_report_with_existing_tests.map do |test_file_with_time|
|
56
|
+
test_execution_time = test_file_with_time.last
|
64
57
|
|
65
|
-
|
66
|
-
time = test_file_with_time[1]
|
67
|
-
time_left = node_tests[node_index][:time_left] - time
|
58
|
+
current_lightest_node = node_tests.min_by { |node| node[:weight] }
|
68
59
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
60
|
+
updated_node_data = {
|
61
|
+
time_left: current_lightest_node[:time_left] - test_execution_time,
|
62
|
+
weight: current_lightest_node[:weight] + test_execution_time,
|
63
|
+
test_files_with_time: current_lightest_node[:test_files_with_time] << test_file_with_time
|
64
|
+
}
|
76
65
|
|
77
|
-
|
78
|
-
@not_assigned_test_files.each do |test_file_with_time|
|
79
|
-
index = node_with_max_time_left
|
80
|
-
time = test_file_with_time[1]
|
81
|
-
node_tests[index][:time_left] -= time
|
82
|
-
node_tests[index][:test_files_with_time] << test_file_with_time
|
66
|
+
current_lightest_node.merge!(updated_node_data)
|
83
67
|
end
|
84
68
|
end
|
85
|
-
|
86
|
-
def node_with_max_time_left
|
87
|
-
node_test = node_tests.max { |a,b| a[:time_left] <=> b[:time_left] }
|
88
|
-
node_test[:node_index]
|
89
|
-
end
|
90
69
|
end
|
91
70
|
end
|
92
71
|
end
|
data/lib/knapsack/version.rb
CHANGED
@@ -118,7 +118,7 @@ describe Knapsack::Distributors::ReportDistributor do
|
|
118
118
|
'c_spec.rb' => 2.0,
|
119
119
|
'd_spec.rb' => 2.5,
|
120
120
|
'a_spec.rb' => 1.0,
|
121
|
-
'b_spec.rb' => 1.5
|
121
|
+
'b_spec.rb' => 1.5
|
122
122
|
}
|
123
123
|
end
|
124
124
|
let(:custom_args) { { ci_node_total: 3 } }
|
@@ -134,6 +134,7 @@ describe Knapsack::Distributors::ReportDistributor do
|
|
134
134
|
expect(distributor.node_tests[0]).to eql({
|
135
135
|
:node_index => 0,
|
136
136
|
:time_left => -0.5,
|
137
|
+
:weight => 9.0,
|
137
138
|
:test_files_with_time => [
|
138
139
|
["g_spec.rb", 9.0]
|
139
140
|
]
|
@@ -143,12 +144,12 @@ describe Knapsack::Distributors::ReportDistributor do
|
|
143
144
|
it do
|
144
145
|
expect(distributor.node_tests[1]).to eql({
|
145
146
|
:node_index => 1,
|
146
|
-
:time_left => 0.
|
147
|
+
:time_left => 0.5,
|
148
|
+
:weight => 8.0,
|
147
149
|
:test_files_with_time => [
|
148
150
|
["f_spec.rb", 3.5],
|
149
151
|
["d_spec.rb", 2.5],
|
150
|
-
["
|
151
|
-
["a_spec.rb", 1.0]
|
152
|
+
["c_spec.rb", 2.0]
|
152
153
|
]
|
153
154
|
})
|
154
155
|
end
|
@@ -156,11 +157,13 @@ describe Knapsack::Distributors::ReportDistributor do
|
|
156
157
|
it do
|
157
158
|
expect(distributor.node_tests[2]).to eql({
|
158
159
|
:node_index => 2,
|
159
|
-
:time_left => 0.
|
160
|
+
:time_left => 0.0,
|
161
|
+
:weight => 8.5,
|
160
162
|
:test_files_with_time => [
|
161
|
-
["i_spec.rb", 3.0],
|
162
163
|
["h_spec.rb", 3.0],
|
163
|
-
["
|
164
|
+
["i_spec.rb", 3.0],
|
165
|
+
["b_spec.rb", 1.5],
|
166
|
+
["a_spec.rb", 1.0]
|
164
167
|
]
|
165
168
|
})
|
166
169
|
end
|
@@ -170,10 +173,9 @@ describe Knapsack::Distributors::ReportDistributor do
|
|
170
173
|
context 'when node exists' do
|
171
174
|
it do
|
172
175
|
expect(distributor.tests_for_node(1)).to eql([
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
'a_spec.rb'
|
176
|
+
"f_spec.rb",
|
177
|
+
"d_spec.rb",
|
178
|
+
"c_spec.rb"
|
177
179
|
])
|
178
180
|
end
|
179
181
|
end
|
@@ -183,4 +185,78 @@ describe Knapsack::Distributors::ReportDistributor do
|
|
183
185
|
end
|
184
186
|
end
|
185
187
|
end
|
188
|
+
|
189
|
+
describe 'algorithmic efficiency' do
|
190
|
+
subject(:node_weights) do
|
191
|
+
distro = distributor
|
192
|
+
distro.assign_test_files_to_node
|
193
|
+
distro.node_tests.map { |node| node[:weight] }
|
194
|
+
end
|
195
|
+
|
196
|
+
before do
|
197
|
+
allow(distributor).to receive(:all_tests).and_return(report.keys)
|
198
|
+
end
|
199
|
+
|
200
|
+
let(:custom_args) { { ci_node_total: 3 } }
|
201
|
+
|
202
|
+
context 'with the most simple example' do
|
203
|
+
let(:report) do
|
204
|
+
{
|
205
|
+
'a_spec.rb' => 1.0,
|
206
|
+
'b_spec.rb' => 1.0,
|
207
|
+
'c_spec.rb' => 1.0,
|
208
|
+
'd_spec.rb' => 1.0,
|
209
|
+
'e_spec.rb' => 1.0,
|
210
|
+
'f_spec.rb' => 1.0,
|
211
|
+
'g_spec.rb' => 1.0,
|
212
|
+
'h_spec.rb' => 1.0,
|
213
|
+
'i_spec.rb' => 1.0
|
214
|
+
}
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'assigns all nodes equally' do
|
218
|
+
expect(node_weights.uniq).to contain_exactly 3.0
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'with a medium difficulty example' do
|
223
|
+
let(:report) do
|
224
|
+
{
|
225
|
+
'a_spec.rb' => 1.0,
|
226
|
+
'b_spec.rb' => 2.0,
|
227
|
+
'c_spec.rb' => 3.0,
|
228
|
+
'd_spec.rb' => 1.0,
|
229
|
+
'e_spec.rb' => 2.0,
|
230
|
+
'f_spec.rb' => 3.0,
|
231
|
+
'g_spec.rb' => 1.0,
|
232
|
+
'h_spec.rb' => 2.0,
|
233
|
+
'i_spec.rb' => 3.0
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'assigns all nodes equally' do
|
238
|
+
expect(node_weights.uniq).to contain_exactly 6.0
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context 'with a difficult example' do
|
243
|
+
let(:report) do
|
244
|
+
{
|
245
|
+
'a_spec.rb' => 2.0,
|
246
|
+
'b_spec.rb' => 2.0,
|
247
|
+
'c_spec.rb' => 3.0,
|
248
|
+
'd_spec.rb' => 1.0,
|
249
|
+
'e_spec.rb' => 1.0,
|
250
|
+
'f_spec.rb' => 1.0,
|
251
|
+
'g_spec.rb' => 9.0,
|
252
|
+
'h_spec.rb' => 1.0,
|
253
|
+
'i_spec.rb' => 10.0
|
254
|
+
}
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'assigns all nodes equally' do
|
258
|
+
expect(node_weights.uniq).to contain_exactly 10.0
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
186
262
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knapsack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|