pwrake 0.9.8 → 0.9.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d50d7fd5c00627f0eea3d59e26632c4e9e4c0f6d
4
- data.tar.gz: 3d9d6638a9dde0ce9feebc1ba210d9ce1d94b310
3
+ metadata.gz: cdc080259b5fb3f1b2c487375c56d2c319c4ad4b
4
+ data.tar.gz: 8f28b6ff5df2e0160abf7c259808d85632c5db27
5
5
  SHA512:
6
- metadata.gz: c7517d29d640a06db61bc8a656615d43706564c49596d594830cadbbe0134b79bfe71c542e182de003baff492b58008bcb90e60b97aab587de1460f21cd99ce6
7
- data.tar.gz: 99f101b28c359ea3157caf688205da6734bb95569dd1eea6fed5cc6787e6b1f9a7bd01a35ab1e7dd694e2782c0969480f4abea1d18bc68d963bc85658d9432c6
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()
@@ -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 + "%s<br/>%.2f%%</td>" % [format_comma(x),x*100.0/sum]
147
- m << td + "%s<br/>%.2f%%</td>" % [format_comma(y),y*100.0/sum]
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
- n_same_input = 0
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>" % @elap_host[h]
224
+ html << "<td align='right'>%.3f</td>" % @stat[h,nil,:elap]
231
225
  html << "<td></td>"
232
- html << tr_count(@n_same_input[h],@n_diff_input[h])
233
- html << tr_count(@size_same_input[h],@size_diff_input[h])
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(@n_same_output[h],@n_diff_output[h])
236
- html << tr_count(@size_same_output[h],@size_diff_output[h])
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>" % elap_host
234
+ html << "<td align='right'>%.3f</td>" % @stat.total(nil,:elap)
251
235
  html << "<td></td>"
252
- html << tr_count(n_same_input,n_diff_input)
253
- html << tr_count(size_same_input,size_diff_input)
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(n_same_output,n_diff_output)
256
- html << tr_count(size_same_output,size_diff_output)
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
- @n_same_output = Hash.new(0)
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Pwrake
2
- VERSION = "0.9.8"
2
+ VERSION = "0.9.9"
3
3
  end
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.8
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: 2013-10-17 00:00:00.000000000 Z
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.3
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