pwrake 0.9.8 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pwrake/locality_aware_queue.rb +70 -0
- data/lib/pwrake/report/report.rb +85 -88
- data/lib/pwrake/task_queue.rb +43 -2
- data/lib/pwrake/version.rb +1 -1
- metadata +6 -8
- data/lib/pwrake/cache_aware_queue.rb +0 -184
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdc080259b5fb3f1b2c487375c56d2c319c4ad4b
|
4
|
+
data.tar.gz: 8f28b6ff5df2e0160abf7c259808d85632c5db27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba5588c3bf612d56321bba8e36d331f2a4404b2815d3765b6b0baf7a483462498e852f31780147c38631c3c11b46ba9583849faeaec00d3792bbff29f9e332fb
|
7
|
+
data.tar.gz: b6dd586b0982cfedd38ea166c9f7621fce13f90af61ad2f0ae334c659b9bd70be014d63c7ed9719c259ae5ca613940ab338fd627c11218fb5f2be3ba5510d08e
|
@@ -6,8 +6,78 @@ module Pwrake
|
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
# copy from ruby's thread.rb
|
10
|
+
class ConditionVariable
|
11
|
+
#
|
12
|
+
# Creates a new ConditionVariable
|
13
|
+
#
|
14
|
+
def initialize
|
15
|
+
@waiters = {}
|
16
|
+
@waiters_mutex = Mutex.new
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
|
21
|
+
#
|
22
|
+
# If +timeout+ is given, this method returns after +timeout+ seconds passed,
|
23
|
+
# even if no other thread doesn't signal.
|
24
|
+
#
|
25
|
+
def wait(mutex, timeout=nil)
|
26
|
+
Thread.handle_interrupt(StandardError => :never) do
|
27
|
+
begin
|
28
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
29
|
+
@waiters_mutex.synchronize do
|
30
|
+
@waiters[Thread.current] = true
|
31
|
+
end
|
32
|
+
mutex.sleep timeout
|
33
|
+
end
|
34
|
+
ensure
|
35
|
+
@waiters_mutex.synchronize do
|
36
|
+
@waiters.delete(Thread.current)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Wakes up the first thread in line waiting for this lock.
|
45
|
+
#
|
46
|
+
def signal
|
47
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
48
|
+
begin
|
49
|
+
t, _ = @waiters_mutex.synchronize { @waiters.shift }
|
50
|
+
t.run if t
|
51
|
+
rescue ThreadError
|
52
|
+
retry # t was already dead?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Wakes up all threads waiting for this lock.
|
60
|
+
#
|
61
|
+
def broadcast
|
62
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
63
|
+
threads = nil
|
64
|
+
@waiters_mutex.synchronize do
|
65
|
+
threads = @waiters.keys
|
66
|
+
@waiters.clear
|
67
|
+
end
|
68
|
+
for t in threads
|
69
|
+
begin
|
70
|
+
t.run
|
71
|
+
rescue ThreadError
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
self
|
76
|
+
end
|
77
|
+
end
|
9
78
|
|
10
79
|
class LocalityConditionVariable < ConditionVariable
|
80
|
+
|
11
81
|
def signal(hints=nil)
|
12
82
|
if hints.nil?
|
13
83
|
super()
|
data/lib/pwrake/report/report.rb
CHANGED
@@ -63,6 +63,8 @@ EOL
|
|
63
63
|
@elap = @end_time - @start_time
|
64
64
|
read_elap_each_cmd
|
65
65
|
make_cmd_stat
|
66
|
+
|
67
|
+
@stat = TaskStat.new(@task_file,@sh_table)
|
66
68
|
end
|
67
69
|
|
68
70
|
attr_reader :base, :ncore, :elap
|
@@ -142,9 +144,11 @@ EOL
|
|
142
144
|
|
143
145
|
def tr_count(x,y)
|
144
146
|
sum = x+y
|
147
|
+
xp = x*100.0/sum
|
148
|
+
yp = y*100.0/sum
|
145
149
|
td = "<td align='right' valign='top'>"
|
146
|
-
m = td +
|
147
|
-
m << td +
|
150
|
+
m = td + '%s<br/>''%.2f%%</td>' % [format_comma(x),xp]
|
151
|
+
m << td + '%s<br/>''%.2f%%</td>' % [format_comma(y),yp]
|
148
152
|
m << td + "%s</td>" % format_comma(sum)
|
149
153
|
m
|
150
154
|
end
|
@@ -192,7 +196,6 @@ EOL
|
|
192
196
|
html << "<table>\n"
|
193
197
|
html << "<img src='./#{File.basename(histogram_plot)}' align='top'/></br>\n"
|
194
198
|
|
195
|
-
task_locality
|
196
199
|
html << "<h2>Locality statistics</h2>\n"
|
197
200
|
html << "<table>\n"
|
198
201
|
|
@@ -216,44 +219,25 @@ EOL
|
|
216
219
|
html << "<th>local</th><th>remote</th><th>total</th>"
|
217
220
|
html << "<th>local</th><th>remote</th><th>total</th>"
|
218
221
|
html << "</tr>\n"
|
219
|
-
|
220
|
-
size_same_input = 0
|
221
|
-
n_diff_input = 0
|
222
|
-
size_diff_input = 0
|
223
|
-
n_same_output = 0
|
224
|
-
size_same_output = 0
|
225
|
-
n_diff_output = 0
|
226
|
-
size_diff_output = 0
|
227
|
-
elap_host = 0
|
228
|
-
@exec_hosts.each do |h|
|
222
|
+
@stat.exec_hosts.each do |h|
|
229
223
|
html << "<tr><td>#{h}</td>"
|
230
|
-
html << "<td align='right'>%.3f</td>" % @
|
224
|
+
html << "<td align='right'>%.3f</td>" % @stat[h,nil,:elap]
|
231
225
|
html << "<td></td>"
|
232
|
-
html << tr_count(@
|
233
|
-
html << tr_count(@
|
226
|
+
html << tr_count(@stat[h,true,:in_num],@stat[h,false,:in_num])
|
227
|
+
html << tr_count(@stat[h,true,:in_size],@stat[h,false,:in_size])
|
234
228
|
html << "<td></td>"
|
235
|
-
html << tr_count(@
|
236
|
-
html << tr_count(@
|
237
|
-
|
229
|
+
html << tr_count(@stat[h,true,:out_num],@stat[h,false,:out_num])
|
230
|
+
html << tr_count(@stat[h,true,:out_size],@stat[h,false,:out_size])
|
238
231
|
html << "</tr>\n"
|
239
|
-
n_same_input += @n_same_input[h]
|
240
|
-
size_same_input += @size_same_input[h]
|
241
|
-
n_diff_input += @n_diff_input[h]
|
242
|
-
size_diff_input += @size_diff_input[h]
|
243
|
-
n_same_output += @n_same_output[h]
|
244
|
-
size_same_output += @size_same_output[h]
|
245
|
-
n_diff_output += @n_diff_output[h]
|
246
|
-
size_diff_output += @size_diff_output[h]
|
247
|
-
elap_host += @elap_host[h]
|
248
232
|
end
|
249
233
|
html << "<tr><td>total</td>"
|
250
|
-
html << "<td align='right'>%.3f</td>" %
|
234
|
+
html << "<td align='right'>%.3f</td>" % @stat.total(nil,:elap)
|
251
235
|
html << "<td></td>"
|
252
|
-
html << tr_count(
|
253
|
-
html << tr_count(
|
236
|
+
html << tr_count(@stat.total(true,:in_num),@stat.total(false,:in_num))
|
237
|
+
html << tr_count(@stat.total(true,:in_size),@stat.total(false,:in_size))
|
254
238
|
html << "<td></td>"
|
255
|
-
html << tr_count(
|
256
|
-
html << tr_count(
|
239
|
+
html << tr_count(@stat.total(true,:out_num),@stat.total(false,:out_num))
|
240
|
+
html << tr_count(@stat.total(true,:out_size),@stat.total(false,:out_size))
|
257
241
|
|
258
242
|
html << "</tr>\n"
|
259
243
|
html << "<table>\n"
|
@@ -262,64 +246,12 @@ EOL
|
|
262
246
|
File.open(@html_file,"w") do |f|
|
263
247
|
f.puts html
|
264
248
|
end
|
265
|
-
puts "generate "+@html_file
|
266
|
-
end
|
267
|
-
|
268
|
-
def task_locality
|
269
|
-
@task_table = CSV.read(@task_file,:headers=>true)
|
270
|
-
file_size = {}
|
271
|
-
file_host = {}
|
272
|
-
@task_table.each do |row|
|
273
|
-
name = row['task_name']
|
274
|
-
file_size[name] = row['file_size'].to_i
|
275
|
-
file_host[name] = (row['file_host']||'').split('|')
|
276
|
-
end
|
249
|
+
#puts "generate "+@html_file
|
277
250
|
|
278
|
-
@
|
279
|
-
@size_same_output= Hash.new(0)
|
280
|
-
@n_diff_output = Hash.new(0)
|
281
|
-
@size_diff_output= Hash.new(0)
|
282
|
-
@n_same_input = Hash.new(0)
|
283
|
-
@size_same_input = Hash.new(0)
|
284
|
-
@n_diff_input = Hash.new(0)
|
285
|
-
@size_diff_input = Hash.new(0)
|
286
|
-
h = {}
|
287
|
-
@task_table.each do |row|
|
288
|
-
if row['executed']=='1'
|
289
|
-
name = row['task_name']
|
290
|
-
exec_host = row['exec_host']
|
291
|
-
h[exec_host] = true
|
292
|
-
if file_host[name].include?(exec_host)
|
293
|
-
@n_same_output[exec_host] += 1
|
294
|
-
@size_same_output[exec_host] += file_size[name]
|
295
|
-
else
|
296
|
-
@n_diff_output[exec_host] += 1
|
297
|
-
@size_diff_output[exec_host] += file_size[name]
|
298
|
-
end
|
299
|
-
preq_files = (row['preq']||'').split('|')
|
300
|
-
preq_files.each do |preq|
|
301
|
-
if (sz=file_size[preq]) && sz > 0
|
302
|
-
if file_host[preq].include?(exec_host)
|
303
|
-
@n_same_input[exec_host] += 1
|
304
|
-
@size_same_input[exec_host] += sz
|
305
|
-
else
|
306
|
-
@n_diff_input[exec_host] += 1
|
307
|
-
@size_diff_input[exec_host] += sz
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
@exec_hosts = h.keys.sort
|
314
|
-
|
315
|
-
@elap_host = Hash.new(0)
|
316
|
-
@sh_table.each do |row|
|
317
|
-
if (h = row['host']) && (t = row['elap_time'])
|
318
|
-
@elap_host[h] += t.to_f
|
319
|
-
end
|
320
|
-
end
|
251
|
+
printf "%s,%d,%d,%d,%d\n",@html_file, @stat.total(true,:in_num),@stat.total(false,:in_num),@stat.total(true,:in_size),@stat.total(false,:in_size)
|
321
252
|
end
|
322
253
|
|
254
|
+
|
323
255
|
def histogram_plot
|
324
256
|
command_list = []
|
325
257
|
@cmd_stat.each do |cmd,stat|
|
@@ -357,7 +289,72 @@ set title 'histogram of elapsed time'"
|
|
357
289
|
hist_image
|
358
290
|
end
|
359
291
|
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class TaskStat
|
295
|
+
|
296
|
+
def initialize(task_file, sh_table)
|
297
|
+
@task_table = CSV.read(task_file,:headers=>true)
|
298
|
+
@count = Hash.new(0)
|
299
|
+
task_locality
|
300
|
+
stat_sh_table(sh_table)
|
301
|
+
end
|
302
|
+
|
303
|
+
attr_reader :exec_hosts
|
304
|
+
|
305
|
+
def count(exec_host, loc, key, val)
|
306
|
+
@count[[exec_host,loc,key]] += val
|
307
|
+
@count[[loc,key]] += val
|
308
|
+
end
|
309
|
+
|
310
|
+
def total(loc,key)
|
311
|
+
@count[[loc,key]]
|
312
|
+
end
|
313
|
+
|
314
|
+
def [](exec_host,loc,key)
|
315
|
+
@count[[exec_host,loc,key]]
|
316
|
+
end
|
317
|
+
|
318
|
+
def task_locality
|
319
|
+
file_size = {}
|
320
|
+
file_host = {}
|
321
|
+
h = {}
|
322
|
+
@task_table.each do |row|
|
323
|
+
name = row['task_name']
|
324
|
+
file_size[name] = row['file_size'].to_i
|
325
|
+
file_host[name] = (row['file_host']||'').split('|')
|
326
|
+
h[row['exec_host']] = true
|
327
|
+
end
|
328
|
+
@exec_hosts = h.keys.sort
|
329
|
+
|
330
|
+
@task_table.each do |row|
|
331
|
+
if row['executed']=='1'
|
332
|
+
name = row['task_name']
|
333
|
+
exec_host = row['exec_host']
|
334
|
+
loc = file_host[name].include?(exec_host)
|
335
|
+
count(exec_host, loc, :out_num, 1)
|
336
|
+
count(exec_host, loc, :out_size, file_size[name])
|
337
|
+
|
338
|
+
preq_files = (row['preq']||'').split('|')
|
339
|
+
preq_files.each do |preq|
|
340
|
+
sz = file_size[preq]
|
341
|
+
if sz && sz > 0
|
342
|
+
loc = file_host[preq].include?(exec_host)
|
343
|
+
count(exec_host, loc, :in_num, 1)
|
344
|
+
count(exec_host, loc, :in_size, sz)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
360
350
|
|
351
|
+
def stat_sh_table(sh_table)
|
352
|
+
sh_table.each do |row|
|
353
|
+
if (h = row['host']) && (t = row['elap_time'])
|
354
|
+
count(h, nil, :elap, t.to_f)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
361
358
|
|
362
359
|
end
|
363
360
|
end
|
data/lib/pwrake/task_queue.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require "pwrake/cache_aware_queue.rb"
|
2
|
-
|
3
1
|
module Pwrake
|
4
2
|
|
5
3
|
class TaskConditionVariable < ConditionVariable
|
@@ -81,6 +79,47 @@ module Pwrake
|
|
81
79
|
end
|
82
80
|
|
83
81
|
|
82
|
+
# LIFO + HRF
|
83
|
+
class LifoHrfQueueArray < Array
|
84
|
+
def initialize(n)
|
85
|
+
@n = (n>0) ? n : 1
|
86
|
+
@count = []
|
87
|
+
end
|
88
|
+
|
89
|
+
def push(t)
|
90
|
+
super(t)
|
91
|
+
r = t.rank
|
92
|
+
@count[r] = (@count[r]||0) + 1
|
93
|
+
end
|
94
|
+
|
95
|
+
def shift
|
96
|
+
if empty?
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
(@count.size-1).downto(0) do |r|
|
100
|
+
c = @count[r]
|
101
|
+
if c && c>0
|
102
|
+
t = (c<=@n) ? pop_last_rank(r) : pop
|
103
|
+
@count[t.rank] -= 1
|
104
|
+
return t
|
105
|
+
end
|
106
|
+
end
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
110
|
+
def pop_last_rank(r)
|
111
|
+
(size-1).downto(0) do |i|
|
112
|
+
t = at(i)
|
113
|
+
if t.rank == r
|
114
|
+
delete_at(i)
|
115
|
+
return t
|
116
|
+
end
|
117
|
+
end
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
|
84
123
|
# Rank-Even Last In First Out
|
85
124
|
class RankQueueArray
|
86
125
|
def initialize(n)
|
@@ -338,6 +377,8 @@ module Pwrake
|
|
338
377
|
@array_class = FifoQueueArray # Array # Fifo
|
339
378
|
when /lifo/i
|
340
379
|
@array_class = LifoQueueArray
|
380
|
+
when /lihr/i
|
381
|
+
@array_class = LifoHrfQueueArray
|
341
382
|
when /rank/i
|
342
383
|
@array_class = RankQueueArray
|
343
384
|
else
|
data/lib/pwrake/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pwrake
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro TANAKA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Parallel workflow extension for Rake
|
14
14
|
email:
|
@@ -18,7 +18,7 @@ executables:
|
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
-
- .gitignore
|
21
|
+
- ".gitignore"
|
22
22
|
- Gemfile
|
23
23
|
- LICENSE.txt
|
24
24
|
- README.md
|
@@ -26,7 +26,6 @@ files:
|
|
26
26
|
- bin/pwrake
|
27
27
|
- lib/pwrake.rb
|
28
28
|
- lib/pwrake/application.rb
|
29
|
-
- lib/pwrake/cache_aware_queue.rb
|
30
29
|
- lib/pwrake/counter.rb
|
31
30
|
- lib/pwrake/file_utils.rb
|
32
31
|
- lib/pwrake/gfarm_feature.rb
|
@@ -77,17 +76,17 @@ require_paths:
|
|
77
76
|
- lib
|
78
77
|
required_ruby_version: !ruby/object:Gem::Requirement
|
79
78
|
requirements:
|
80
|
-
- -
|
79
|
+
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
82
81
|
version: '0'
|
83
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
83
|
requirements:
|
85
|
-
- -
|
84
|
+
- - ">="
|
86
85
|
- !ruby/object:Gem::Version
|
87
86
|
version: '0'
|
88
87
|
requirements: []
|
89
88
|
rubyforge_project:
|
90
|
-
rubygems_version: 2.0
|
89
|
+
rubygems_version: 2.2.0
|
91
90
|
signing_key:
|
92
91
|
specification_version: 4
|
93
92
|
summary: Adding Parallel and Distributed feature to Rake
|
@@ -109,4 +108,3 @@ test_files:
|
|
109
108
|
- spec/helper.rb
|
110
109
|
- spec/hosts
|
111
110
|
- spec/pwrake_spec.rb
|
112
|
-
has_rdoc:
|
@@ -1,184 +0,0 @@
|
|
1
|
-
module Pwrake
|
2
|
-
|
3
|
-
class MTimePriorityArray < Array
|
4
|
-
|
5
|
-
def order_by(item)
|
6
|
-
item.input_file_mtime
|
7
|
-
end
|
8
|
-
|
9
|
-
def push(t)
|
10
|
-
order_value = order_by(t)
|
11
|
-
if empty? || order_by(last) <= order_value
|
12
|
-
super(t)
|
13
|
-
elsif order_by(first) > order_value
|
14
|
-
unshift(t)
|
15
|
-
else
|
16
|
-
lower = 0
|
17
|
-
upper = size-1
|
18
|
-
while lower+1 < upper
|
19
|
-
mid = ((lower + upper) / 2).to_i
|
20
|
-
if order_by(self[mid]) <= order_value
|
21
|
-
lower = mid
|
22
|
-
else
|
23
|
-
upper = mid
|
24
|
-
end
|
25
|
-
end
|
26
|
-
insert(upper,t)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def index(t)
|
31
|
-
if size < 40
|
32
|
-
return super(t)
|
33
|
-
end
|
34
|
-
order_value = t.order_by
|
35
|
-
if order_by(last) < order_value || order_by(first) > order_value
|
36
|
-
nil
|
37
|
-
else
|
38
|
-
lower = 0
|
39
|
-
upper = size-1
|
40
|
-
while lower+1 < upper
|
41
|
-
mid = ((lower + upper) / 2).to_i
|
42
|
-
if order_by(self[mid]) < order_value
|
43
|
-
lower = mid
|
44
|
-
else
|
45
|
-
upper = mid
|
46
|
-
end
|
47
|
-
end
|
48
|
-
mid = upper
|
49
|
-
if order_by(self[mid]) == order_value
|
50
|
-
Log.debug "--- TQA#index=#{mid}, order_value=#{order_value}"
|
51
|
-
mid
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
# rank-Even Last In First Out
|
59
|
-
class CacheAwareQueue
|
60
|
-
def initialize(n)
|
61
|
-
@q = []
|
62
|
-
@i = 0
|
63
|
-
@size = 0
|
64
|
-
@n = (n>0) ? n : 1
|
65
|
-
end
|
66
|
-
|
67
|
-
def push(t)
|
68
|
-
r = t.rank
|
69
|
-
a = @q[r]
|
70
|
-
if a.nil?
|
71
|
-
@q[r] = a = MTimePriorityArray.new
|
72
|
-
end
|
73
|
-
@size += 1
|
74
|
-
a.push(t)
|
75
|
-
end
|
76
|
-
|
77
|
-
def size
|
78
|
-
@size
|
79
|
-
end
|
80
|
-
|
81
|
-
def empty?
|
82
|
-
@size == 0
|
83
|
-
end
|
84
|
-
|
85
|
-
def shift
|
86
|
-
if empty?
|
87
|
-
return nil
|
88
|
-
elsif @size < @n*2
|
89
|
-
return shift_high_rank
|
90
|
-
else
|
91
|
-
return shift_weighted
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def shift_high_rank
|
96
|
-
(@q.size-1).downto(0) do |i|
|
97
|
-
a = @q[i]
|
98
|
-
next if a.nil? || a.empty?
|
99
|
-
@size -= 1
|
100
|
-
return pop_last_max(a)
|
101
|
-
end
|
102
|
-
nil
|
103
|
-
end
|
104
|
-
|
105
|
-
def shift_weighted
|
106
|
-
weight, weight_avg = RANK_STAT.rank_weight
|
107
|
-
wsum = 0.0
|
108
|
-
q = []
|
109
|
-
@q.each_with_index do |a,i|
|
110
|
-
next if a.nil? || a.empty?
|
111
|
-
w = weight[i]
|
112
|
-
w = weight_avg if w.nil?
|
113
|
-
# w *= a.size
|
114
|
-
wsum += w
|
115
|
-
q << [a,wsum]
|
116
|
-
end
|
117
|
-
#
|
118
|
-
x = rand() * wsum
|
119
|
-
Log.debug "--- shift_weighted x=#{x} wsum=#{wsum} weight=#{weight.inspect}"
|
120
|
-
@size -= 1
|
121
|
-
q.each do |a,w|
|
122
|
-
if w > x
|
123
|
-
return a.pop
|
124
|
-
end
|
125
|
-
end
|
126
|
-
raise "ELIFO: wsum=#{wsum} x=#{x}"
|
127
|
-
end
|
128
|
-
|
129
|
-
def pop_last_max(a)
|
130
|
-
if a.size < 2
|
131
|
-
return a.pop
|
132
|
-
end
|
133
|
-
y_max = nil
|
134
|
-
i_max = nil
|
135
|
-
n = [@n, a.size].min
|
136
|
-
(-n..-1).each do |i|
|
137
|
-
y = a[i].input_file_size
|
138
|
-
if y_max.nil? || y > y_max
|
139
|
-
y_max = y
|
140
|
-
i_max = i
|
141
|
-
end
|
142
|
-
end
|
143
|
-
a.delete_at(i_max)
|
144
|
-
end
|
145
|
-
|
146
|
-
def first
|
147
|
-
return nil if empty?
|
148
|
-
@q.size.times do |i|
|
149
|
-
a = @q[i]
|
150
|
-
unless a.nil? || a.empty?
|
151
|
-
return a.first
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def last
|
157
|
-
return nil if empty?
|
158
|
-
@q.size.times do |i|
|
159
|
-
a = @q[-i-1]
|
160
|
-
unless a.nil? || a.empty?
|
161
|
-
return a.last
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def delete(t)
|
167
|
-
n = 0
|
168
|
-
@q.each do |a|
|
169
|
-
if a
|
170
|
-
a.delete(t)
|
171
|
-
n += a.size
|
172
|
-
end
|
173
|
-
end
|
174
|
-
@size = n
|
175
|
-
end
|
176
|
-
|
177
|
-
def clear
|
178
|
-
@q.clear
|
179
|
-
@i = 0
|
180
|
-
@size = 0
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|