pwrake 0.9.5 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +83 -4
- data/lib/pwrake/application.rb +34 -0
- data/lib/pwrake/file_utils.rb +43 -16
- data/lib/pwrake/gfarm_feature.rb +79 -40
- data/lib/pwrake/locality_aware_queue.rb +141 -111
- data/lib/pwrake/logger.rb +7 -1
- data/lib/pwrake/master.rb +21 -2
- data/lib/pwrake/option.rb +106 -56
- data/lib/pwrake/profiler.rb +44 -12
- data/lib/pwrake/report/parallelism.rb +262 -0
- data/lib/pwrake/report/report.rb +355 -0
- data/lib/pwrake/report/report_multi.rb +196 -0
- data/lib/pwrake/report/stat.rb +115 -0
- data/lib/pwrake/report.rb +6 -0
- data/lib/pwrake/shell.rb +30 -10
- data/lib/pwrake/task_algorithm.rb +174 -50
- data/lib/pwrake/task_queue.rb +130 -50
- data/lib/pwrake/version.rb +1 -1
- data/spec/004/Rakefile +1 -1
- data/spec/009/pwrake_conf.yaml +1 -0
- data/spec/011/Rakefile +15 -0
- data/spec/helper.rb +7 -3
- data/spec/pwrake_spec.rb +12 -0
- metadata +15 -9
data/lib/pwrake/profiler.rb
CHANGED
@@ -2,9 +2,19 @@ module Pwrake
|
|
2
2
|
|
3
3
|
class Profiler
|
4
4
|
|
5
|
+
HEADER_FOR_PROFILE =
|
6
|
+
%w[exec_id task_id task_name command
|
7
|
+
start_time end_time elap_time host status]
|
8
|
+
|
9
|
+
HEADER_FOR_GNU_TIME =
|
10
|
+
%w[realtime systime usrtime maxrss averss memsz
|
11
|
+
datasz stcksz textsz pagesz majflt minflt nswap ncswinv
|
12
|
+
ncswvol ninp nout msgrcv msgsnd signum]
|
13
|
+
|
5
14
|
def initialize
|
6
15
|
@lock = Mutex.new
|
7
16
|
@separator = ","
|
17
|
+
@re_escape = /\s#{Regexp.escape(@separator)}/
|
8
18
|
@gnu_time = false
|
9
19
|
@id = 0
|
10
20
|
@io = nil
|
@@ -12,20 +22,30 @@ module Pwrake
|
|
12
22
|
|
13
23
|
attr_accessor :separator, :gnu_time
|
14
24
|
|
15
|
-
def open(file,gnu_time)
|
25
|
+
def open(file,gnu_time=false,plot=false)
|
26
|
+
@file = file
|
16
27
|
@gnu_time = gnu_time
|
28
|
+
@plot = plot
|
17
29
|
@lock.synchronize do
|
18
30
|
@io.close if @io != nil
|
19
31
|
@io = File.open(file,"w")
|
20
32
|
end
|
21
33
|
_puts table_header
|
34
|
+
t = Time.now
|
35
|
+
profile(nil,'pwrake_profile_start',t,t)
|
22
36
|
end
|
23
37
|
|
24
38
|
def close
|
39
|
+
t = Time.now
|
40
|
+
profile(nil,'pwrake_profile_end',t,t)
|
25
41
|
@lock.synchronize do
|
26
42
|
@io.close if @io != nil
|
27
43
|
@io = nil
|
28
44
|
end
|
45
|
+
if @plot
|
46
|
+
require 'pwrake/report'
|
47
|
+
Parallelism.plot_parallelism(@file)
|
48
|
+
end
|
29
49
|
end
|
30
50
|
|
31
51
|
def _puts(s)
|
@@ -35,11 +55,9 @@ module Pwrake
|
|
35
55
|
end
|
36
56
|
|
37
57
|
def table_header
|
38
|
-
a =
|
58
|
+
a = HEADER_FOR_PROFILE
|
39
59
|
if @gnu_time
|
40
|
-
a
|
41
|
-
datasz stcksz textsz pagesz majflt minflt nswap ncswinv
|
42
|
-
ncswvol ninp nout msgrcv msgsnd signum]
|
60
|
+
a += HEADER_FOR_GNU_TIME
|
43
61
|
end
|
44
62
|
a.join(@separator)
|
45
63
|
end
|
@@ -56,27 +74,41 @@ module Pwrake
|
|
56
74
|
else
|
57
75
|
"#{cmd}\necho '#{terminator}':$? "
|
58
76
|
end
|
59
|
-
end
|
77
|
+
end #`
|
60
78
|
|
61
79
|
def format_time(t)
|
62
|
-
t.utc.strftime("%F %T.%L")
|
80
|
+
#t.utc.strftime("%F %T.%L")
|
81
|
+
t.strftime("%F %T.%L")
|
63
82
|
end
|
64
83
|
|
65
|
-
def
|
84
|
+
def self.format_time(t)
|
85
|
+
t.strftime("%F %T.%L")
|
86
|
+
end
|
87
|
+
|
88
|
+
def profile(task, cmd, start_time, end_time, host="", status="")
|
66
89
|
id = @lock.synchronize do
|
67
90
|
id = @id
|
68
91
|
@id += 1
|
69
92
|
id
|
70
93
|
end
|
71
94
|
if @io
|
72
|
-
|
73
|
-
|
95
|
+
if task.kind_of? Rake::Task
|
96
|
+
tname = task.name.inspect
|
97
|
+
task_id = task.task_id
|
98
|
+
else
|
99
|
+
tname = ""
|
100
|
+
task_id = ""
|
101
|
+
end
|
102
|
+
host = '"'+host+'"' if @re_escape =~ host
|
103
|
+
_puts [id, task_id, tname, cmd.inspect,
|
74
104
|
format_time(start_time),
|
75
105
|
format_time(end_time),
|
76
106
|
"%.3f" % (end_time-start_time),
|
77
|
-
status].join(@separator)
|
107
|
+
host, status].join(@separator)
|
78
108
|
end
|
79
|
-
if
|
109
|
+
if status==""
|
110
|
+
1
|
111
|
+
elsif @gnu_time
|
80
112
|
/^([^,]*),/ =~ status
|
81
113
|
Integer($1)
|
82
114
|
else
|
@@ -0,0 +1,262 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
module Parallelism
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def count_start_end_from_csv(file)
|
7
|
+
a = []
|
8
|
+
start_time = nil
|
9
|
+
|
10
|
+
CSV.foreach(file,:headers=>true) do |row|
|
11
|
+
if row['command'] == 'pwrake_profile_start'
|
12
|
+
start_time = Time.parse(row['start_time'])
|
13
|
+
elsif row['command'] == 'pwrake_profile_end'
|
14
|
+
t = Time.parse(row['start_time']) - start_time
|
15
|
+
a << [t,0]
|
16
|
+
elsif start_time
|
17
|
+
t = Time.parse(row['start_time']) - start_time
|
18
|
+
a << [t,+1]
|
19
|
+
t = Time.parse(row['end_time']) - start_time
|
20
|
+
a << [t,-1]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
a.sort{|x,y| x[0]<=>y[0]}
|
25
|
+
end
|
26
|
+
|
27
|
+
def exec_density(a)
|
28
|
+
reso = 0.1
|
29
|
+
delta = 1/reso
|
30
|
+
t_end = (a.last)[0]
|
31
|
+
n = (t_end/reso).to_i + 1
|
32
|
+
i = 0
|
33
|
+
t_next = reso
|
34
|
+
d = (n+1).times.map{|i| [reso*i,0]}
|
35
|
+
a.each do |x|
|
36
|
+
while d[i+1][0] <= x[0]
|
37
|
+
i += 1
|
38
|
+
end
|
39
|
+
if x[1] == 1
|
40
|
+
d[i][1] += delta
|
41
|
+
end
|
42
|
+
end
|
43
|
+
d
|
44
|
+
end
|
45
|
+
|
46
|
+
def plot_parallelism(file)
|
47
|
+
a = count_start_end_from_csv(file)
|
48
|
+
return if a.size < 4
|
49
|
+
|
50
|
+
density = exec_density(a)
|
51
|
+
|
52
|
+
base = file.sub(/\.csv$/,"")
|
53
|
+
fpara = base+"_para.dat"
|
54
|
+
|
55
|
+
n = a.size
|
56
|
+
i = 0
|
57
|
+
y = 0
|
58
|
+
y_max = 0
|
59
|
+
|
60
|
+
File.open(fpara,"w") do |f|
|
61
|
+
begin
|
62
|
+
t = 0
|
63
|
+
y_pre = 0
|
64
|
+
n.times do |i|
|
65
|
+
if a[i][0]-t > 0.001
|
66
|
+
f.printf "%.3f %d\n", t, y_pre
|
67
|
+
t = a[i][0]
|
68
|
+
f.printf "%.3f %d\n", t, y
|
69
|
+
end
|
70
|
+
y += a[i][1]
|
71
|
+
y_pre = y
|
72
|
+
y_max = y if y > y_max
|
73
|
+
end
|
74
|
+
rescue
|
75
|
+
p a[i]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
t_end = (a.last)[0]
|
80
|
+
|
81
|
+
IO.popen("gnuplot","r+") do |f|
|
82
|
+
f.puts "
|
83
|
+
set terminal png
|
84
|
+
set output '#{base}.png'
|
85
|
+
#set rmargin 10
|
86
|
+
set title '#{base}'
|
87
|
+
set xlabel 'time (sec)'
|
88
|
+
set ylabel 'parallelism'
|
89
|
+
|
90
|
+
set arrow 1 from #{t_end},#{y_max*0.5} to #{t_end},0 linecolor rgb 'blue'
|
91
|
+
set label 1 at first #{t_end},#{y_max*0.5} right \"#{t_end}\\nsec\" textcolor rgb 'blue'
|
92
|
+
|
93
|
+
plot '#{fpara}' w l axis x1y1 title 'parallelism'
|
94
|
+
"
|
95
|
+
end
|
96
|
+
|
97
|
+
#puts "Parallelism plot: #{base}.png"
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def plot_parallelism2(file)
|
102
|
+
a = count_start_end_from_csv(file)
|
103
|
+
return if a.size < 4
|
104
|
+
|
105
|
+
density = exec_density(a)
|
106
|
+
|
107
|
+
base = file.sub(/\.csv$/,"")
|
108
|
+
fpara = base+"_para.dat"
|
109
|
+
fdens = base+'_dens.dat'
|
110
|
+
fimg = base+'.png'
|
111
|
+
|
112
|
+
File.open(fdens,"w") do |f|
|
113
|
+
density.each do |t,d|
|
114
|
+
f.puts "#{t} #{d}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
n = a.size
|
119
|
+
i = 0
|
120
|
+
y = 0
|
121
|
+
y_max = 0
|
122
|
+
|
123
|
+
File.open(fpara,"w") do |f|
|
124
|
+
begin
|
125
|
+
t = 0
|
126
|
+
y_pre = 0
|
127
|
+
n.times do |i|
|
128
|
+
if a[i][0]-t > 0.001
|
129
|
+
f.printf "%.3f %d\n", t, y_pre
|
130
|
+
t = a[i][0]
|
131
|
+
f.printf "%.3f %d\n", t, y
|
132
|
+
end
|
133
|
+
y += a[i][1]
|
134
|
+
y_pre = y
|
135
|
+
y_max = y if y > y_max
|
136
|
+
end
|
137
|
+
rescue
|
138
|
+
p a[i]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
t_end = (a.last)[0]
|
143
|
+
|
144
|
+
IO.popen("gnuplot","r+") do |f|
|
145
|
+
f.puts "
|
146
|
+
set terminal png
|
147
|
+
set output '#{fimg}'
|
148
|
+
#set rmargin 10
|
149
|
+
set title '#{base}'
|
150
|
+
set xlabel 'time (sec)'
|
151
|
+
set ylabel 'parallelism'
|
152
|
+
set y2tics
|
153
|
+
set ytics nomirror
|
154
|
+
set y2label 'exec/sec'
|
155
|
+
|
156
|
+
set arrow 1 from #{t_end},#{y_max*0.5} to #{t_end},0 linecolor rgb 'blue'
|
157
|
+
set label 1 \"#{t_end}\\nsec\" at first #{t_end},#{y_max*0.5} right front textcolor rgb 'blue'
|
158
|
+
|
159
|
+
plot '#{fpara}' w l axis x1y1 title 'parallelism', '#{fdens}' w l axis x1y2 title 'exec/sec'
|
160
|
+
"
|
161
|
+
end
|
162
|
+
|
163
|
+
#puts "Parallelism plot: #{fimg}"
|
164
|
+
fimg
|
165
|
+
end
|
166
|
+
|
167
|
+
def read_time_by_host_from_csv(csvtable)
|
168
|
+
a = {}
|
169
|
+
start_time = nil
|
170
|
+
|
171
|
+
csvtable.each do |row|
|
172
|
+
host = row['host']
|
173
|
+
if row['command'] == 'pwrake_profile_start'
|
174
|
+
start_time = Time.parse(row['start_time'])
|
175
|
+
elsif row['command'] == 'pwrake_profile_end'
|
176
|
+
t = Time.parse(row['start_time']) - start_time
|
177
|
+
a.each do |h,v|
|
178
|
+
v << [t,0]
|
179
|
+
end
|
180
|
+
elsif start_time
|
181
|
+
a[host] ||= []
|
182
|
+
t = Time.parse(row['start_time']) - start_time
|
183
|
+
a[host] << [t,+1]
|
184
|
+
t = Time.parse(row['end_time']) - start_time
|
185
|
+
a[host] << [t,-1]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
a
|
189
|
+
end
|
190
|
+
|
191
|
+
def timeline_to_grid(a)
|
192
|
+
resolution = Rational(1,10)
|
193
|
+
|
194
|
+
a = a.sort{|x,y| x[0]<=>y[0]}
|
195
|
+
t_end = (a.last)[0]
|
196
|
+
|
197
|
+
ngrid = (t_end/resolution).floor
|
198
|
+
grid = [[0,0]]
|
199
|
+
|
200
|
+
j = 0
|
201
|
+
a.each do |x|
|
202
|
+
i = (x[0]/resolution).floor
|
203
|
+
while j < i
|
204
|
+
grid[j+1] = [j*resolution,grid[j][1]]
|
205
|
+
j += 1
|
206
|
+
end
|
207
|
+
grid[i][1] += x[1]
|
208
|
+
end
|
209
|
+
return grid
|
210
|
+
end
|
211
|
+
|
212
|
+
def plot_parallelizm_by_host(csvtable,base)
|
213
|
+
fpng = base+"_para_host.png"
|
214
|
+
data = read_time_by_host_from_csv(csvtable)
|
215
|
+
#return if data.size < 4
|
216
|
+
|
217
|
+
grid = []
|
218
|
+
hosts = data.keys.sort
|
219
|
+
hosts.each do |h|
|
220
|
+
a = timeline_to_grid(data[h])
|
221
|
+
grid << a
|
222
|
+
end
|
223
|
+
|
224
|
+
IO.popen("gnuplot","r+") do |f|
|
225
|
+
f.puts "
|
226
|
+
set terminal png
|
227
|
+
set output '#{fpng}'
|
228
|
+
#set rmargin 7
|
229
|
+
set lmargin 16
|
230
|
+
set pm3d map
|
231
|
+
set pm3d corners2color c1
|
232
|
+
set xlabel 'time (sec)'
|
233
|
+
set ytics nomirror
|
234
|
+
set ticslevel 0
|
235
|
+
set format y ''
|
236
|
+
"
|
237
|
+
hosts.each_with_index do |h,i|
|
238
|
+
if /^([^.]+)\./ =~ h
|
239
|
+
h = $1
|
240
|
+
end
|
241
|
+
f.puts "set ytics add ('#{h}' #{i+0.5})"
|
242
|
+
end
|
243
|
+
f.puts "splot '-' using 2:1:3 with pm3d title ''"
|
244
|
+
|
245
|
+
grid.each_with_index do |a,j|
|
246
|
+
a.each do |x|
|
247
|
+
f.printf "%g %g %d\n", j, x[0], x[1]
|
248
|
+
end
|
249
|
+
f.printf "\n"
|
250
|
+
end
|
251
|
+
j = grid.size
|
252
|
+
grid[j-1].each do |x|
|
253
|
+
f.printf "%g %g %d\n", j, x[0], x[1]
|
254
|
+
end
|
255
|
+
f.printf "e\n"
|
256
|
+
end
|
257
|
+
#puts "Parallelism by host: "+fpng
|
258
|
+
fpng
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
end
|