perfmonger 0.8.2 → 0.9.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/.gitignore +3 -0
- data/NEWS +10 -2
- data/core/Makefile +14 -2
- data/core/build.sh +1 -1
- data/core/perfmonger-plot-formatter.go +325 -0
- data/core/subsystem/usage.go +13 -1
- data/lib/perfmonger.rb +1 -0
- data/lib/perfmonger/command/core.rb +4 -0
- data/lib/perfmonger/command/fingerprint.rb +48 -0
- data/lib/perfmonger/command/init-shell.rb +51 -0
- data/lib/perfmonger/command/plot.rb +241 -195
- data/lib/perfmonger/command/summary.rb +1 -1
- data/lib/perfmonger/version.rb +1 -1
- data/misc/{perfmonger-completion.bash → perfmonger.bash} +0 -0
- data/misc/{_perfmonger → perfmonger.zsh} +24 -8
- data/perfmonger.gemspec +0 -1
- data/spec/fingerprint_spec.rb +7 -7
- data/spec/live_spec.rb +5 -4
- data/spec/perfmonger_spec.rb +7 -7
- data/spec/play_spec.rb +4 -3
- data/spec/plot_spec.rb +18 -17
- data/spec/record_spec.rb +3 -3
- data/spec/stat_spec.rb +2 -2
- data/spec/summary_spec.rb +4 -4
- data/spec/support/aruba.rb +1 -2
- metadata +9 -18
@@ -69,6 +69,18 @@ EOS
|
|
69
69
|
save_disk_info()
|
70
70
|
end
|
71
71
|
|
72
|
+
do_with_message("Saving fdisk info") do
|
73
|
+
save_fdisk_info()
|
74
|
+
end
|
75
|
+
|
76
|
+
do_with_message("Saving lsblk info") do
|
77
|
+
save_lsblk_info()
|
78
|
+
end
|
79
|
+
|
80
|
+
do_with_message("Saving LVM info") do
|
81
|
+
save_lvm_info()
|
82
|
+
end
|
83
|
+
|
72
84
|
do_with_message("Saving PCI/PCIe info") do
|
73
85
|
save_pci_info()
|
74
86
|
end
|
@@ -110,6 +122,8 @@ EOS
|
|
110
122
|
|
111
123
|
FileUtils.mv(tmptar_path, @output_tarball)
|
112
124
|
end
|
125
|
+
|
126
|
+
true
|
113
127
|
end
|
114
128
|
|
115
129
|
private
|
@@ -210,6 +224,40 @@ EOS
|
|
210
224
|
end
|
211
225
|
end
|
212
226
|
|
227
|
+
def save_fdisk_info()
|
228
|
+
fdisk_bin = find_executable("fdisk")
|
229
|
+
|
230
|
+
File.open("#{@output_dir}/fdisk.log", "w") do |f|
|
231
|
+
f.puts(`#{fdisk_bin} -l`)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def save_lsblk_info()
|
236
|
+
lsblk_bin = find_executable("lsblk")
|
237
|
+
|
238
|
+
File.open("#{@output_dir}/lsblk.log", "w") do |f|
|
239
|
+
f.puts(`#{lsblk_bin} -t`)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def save_lvm_info()
|
244
|
+
vgdisplay_bin = find_executable("vgdisplay")
|
245
|
+
lvdisplay_bin = find_executable("lvdisplay")
|
246
|
+
pvdisplay_bin = find_executable("pvdisplay")
|
247
|
+
|
248
|
+
File.open("#{@output_dir}/lvm-vgdisplay.log", "w") do |f|
|
249
|
+
f.puts(`#{vgdisplay_bin}`)
|
250
|
+
end
|
251
|
+
|
252
|
+
File.open("#{@output_dir}/lvm-lvdisplay.log", "w") do |f|
|
253
|
+
f.puts(`#{lvdisplay_bin}`)
|
254
|
+
end
|
255
|
+
|
256
|
+
File.open("#{@output_dir}/lvm-pvdisplay.log", "w") do |f|
|
257
|
+
f.puts(`#{pvdisplay_bin}`)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
213
261
|
def save_irq_info()
|
214
262
|
File.open("#{@output_dir}/irq-smp-affinity.log", "w") do |f|
|
215
263
|
Dir.glob('/proc/irq/*/smp_affinity').sort_by do |path|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
require 'optparse'
|
3
|
+
require 'json'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'tmpdir'
|
6
|
+
|
7
|
+
module PerfMonger
|
8
|
+
module Command
|
9
|
+
|
10
|
+
class InitShellCommand < BaseCommand
|
11
|
+
register_command 'init-shell', "Generate shell script to init shell completion"
|
12
|
+
|
13
|
+
def run(argv)
|
14
|
+
gem_dir = File.expand_path("../../../", __dir__)
|
15
|
+
|
16
|
+
shell = `ps -p #{Process.ppid()} -o 'args='`.strip
|
17
|
+
shell = File.basename(shell.split.first)
|
18
|
+
|
19
|
+
case shell
|
20
|
+
when "zsh"
|
21
|
+
if argv.first == "-"
|
22
|
+
puts <<EOS
|
23
|
+
source #{File.expand_path("misc/perfmonger.zsh", gem_dir)}
|
24
|
+
EOS
|
25
|
+
else
|
26
|
+
puts <<EOS
|
27
|
+
# Add a following line to ~/.zshrc
|
28
|
+
|
29
|
+
eval "$(perfmonger init-shell -)"
|
30
|
+
EOS
|
31
|
+
end
|
32
|
+
when "bash"
|
33
|
+
if argv.first == "-"
|
34
|
+
puts <<EOS
|
35
|
+
source #{File.expand_path("misc/perfmonger.bash", gem_dir)}
|
36
|
+
EOS
|
37
|
+
else
|
38
|
+
puts <<EOS
|
39
|
+
# Add a following line to ~/.bashrc
|
40
|
+
|
41
|
+
eval "$(perfmonger init-shell -)"
|
42
|
+
EOS
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end # module Command
|
51
|
+
end # module PerfMonger
|
@@ -25,6 +25,9 @@ EOS
|
|
25
25
|
@output_prefix = ''
|
26
26
|
@save_gpfiles = false
|
27
27
|
@disk_only_regex = nil
|
28
|
+
@disk_plot_read = true
|
29
|
+
@disk_plot_write = true
|
30
|
+
@disk_numkey_threshold = 10
|
28
31
|
end
|
29
32
|
|
30
33
|
def parse_args(argv)
|
@@ -77,6 +80,25 @@ EOS
|
|
77
80
|
@disk_only_regex = Regexp.compile(regex)
|
78
81
|
end
|
79
82
|
|
83
|
+
@parser.on('--disk-read-only', "Plot only READ performance for disks") do
|
84
|
+
@disk_plot_read = true
|
85
|
+
@disk_plot_write = false
|
86
|
+
end
|
87
|
+
|
88
|
+
@parser.on('--disk-write-only', "Plot only WRITE performance for disks") do
|
89
|
+
@disk_plot_read = false
|
90
|
+
@disk_plot_write = true
|
91
|
+
end
|
92
|
+
|
93
|
+
@parser.on('--disk-read-write', "Plot READ and WRITE performance for disks") do
|
94
|
+
@disk_plot_read = true
|
95
|
+
@disk_plot_write = true
|
96
|
+
end
|
97
|
+
|
98
|
+
@parser.on('--disk-numkey-threshold NUM', "Legends of per-disk plots are turned off if the number of disks is larger than this value.") do |num|
|
99
|
+
@disk_numkey_threshold = num.to_i
|
100
|
+
end
|
101
|
+
|
80
102
|
@parser.parse!(argv)
|
81
103
|
|
82
104
|
if argv.size == 0
|
@@ -104,87 +126,133 @@ EOS
|
|
104
126
|
exit(false)
|
105
127
|
end
|
106
128
|
|
107
|
-
|
129
|
+
formatter_bin = ::PerfMonger::Command::CoreFinder.plot_formatter()
|
130
|
+
|
131
|
+
@tmpdir = Dir.mktmpdir
|
132
|
+
|
133
|
+
@disk_dat = File.expand_path("disk.dat", @tmpdir)
|
134
|
+
@cpu_dat = File.expand_path("cpu.dat", @tmpdir)
|
108
135
|
|
109
|
-
|
110
|
-
IO.popen([
|
111
|
-
|
136
|
+
meta_json = nil
|
137
|
+
IO.popen([formatter_bin, "-perfmonger", @data_file, "-cpufile", @cpu_dat, "-diskfile", @disk_dat], "r") do |io|
|
138
|
+
meta_json = io.read
|
112
139
|
end
|
113
|
-
|
140
|
+
if $?.exitstatus != 0
|
141
|
+
puts("ERROR: failed to run perfmonger-plot-formatter")
|
142
|
+
exit(false)
|
143
|
+
end
|
144
|
+
meta = JSON.parse(meta_json)
|
145
|
+
|
146
|
+
plot_disk(meta)
|
147
|
+
plot_cpu(meta)
|
114
148
|
|
115
|
-
|
116
|
-
plot_cpuinfo(tmpfile.path)
|
149
|
+
true
|
117
150
|
end
|
118
151
|
|
119
152
|
private
|
120
|
-
def
|
121
|
-
iops_pdf_filename = @output_prefix + 'iops.pdf'
|
122
|
-
transfer_pdf_filename = @output_prefix + 'transfer.pdf'
|
123
|
-
|
124
|
-
|
153
|
+
def plot_disk(meta)
|
154
|
+
iops_pdf_filename = @output_prefix + 'disk-iops.pdf'
|
155
|
+
transfer_pdf_filename = @output_prefix + 'disk-transfer.pdf'
|
156
|
+
total_iops_pdf_filename = @output_prefix + 'disk-total-iops.pdf'
|
157
|
+
total_transfer_pdf_filename = @output_prefix + 'disk-total-transfer.pdf'
|
158
|
+
gp_filename = @output_prefix + 'disk.gp'
|
159
|
+
dat_filename = @output_prefix + 'disk.dat'
|
125
160
|
if @output_type != 'pdf'
|
126
|
-
iops_img_filename = @output_prefix + 'iops.' + @output_type
|
127
|
-
transfer_img_filename = @output_prefix + 'transfer.' + @output_type
|
161
|
+
iops_img_filename = @output_prefix + 'disk-iops.' + @output_type
|
162
|
+
transfer_img_filename = @output_prefix + 'disk-transfer.' + @output_type
|
163
|
+
total_iops_img_filename = @output_prefix + 'disk-total-iops.' + @output_type
|
164
|
+
total_transfer_img_filename = @output_prefix + 'disk-total-transfer.' + @output_type
|
128
165
|
else
|
129
166
|
iops_img_filename = nil
|
130
167
|
transfer_img_filename = nil
|
168
|
+
total_iops_img_filename = nil
|
169
|
+
total_transfer_img_filename = nil
|
131
170
|
end
|
132
171
|
|
133
|
-
|
134
|
-
|
135
|
-
datafile = File.open(dat_filename, 'w')
|
136
|
-
gpfile = File.new(gp_filename, 'w')
|
172
|
+
start_time = meta["start_time"]
|
173
|
+
end_time = meta["end_time"]
|
137
174
|
|
138
|
-
|
139
|
-
|
175
|
+
Dir.chdir(@tmpdir) do
|
176
|
+
gpfile = File.new(gp_filename, 'w')
|
140
177
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
178
|
+
total_iops_plot_stmt_list = []
|
179
|
+
iops_plot_stmt_list = meta["disk"]["devices"].map do |dev_entry|
|
180
|
+
devname = dev_entry["name"]
|
181
|
+
idx = dev_entry["idx"]
|
182
|
+
|
183
|
+
if devname == "total"
|
184
|
+
if @disk_plot_read
|
185
|
+
total_iops_plot_stmt_list.push("\"disk.dat\" ind #{idx} usi 1:2 with lines lw 2 title \"#{devname} read\"")
|
186
|
+
end
|
187
|
+
if @disk_plot_write
|
188
|
+
total_iops_plot_stmt_list.push("\"disk.dat\" ind #{idx} usi 1:3 with lines lw 2 title \"#{devname} write\"")
|
189
|
+
end
|
146
190
|
|
147
|
-
|
148
|
-
|
191
|
+
[]
|
192
|
+
elsif @disk_only_regex && !(devname =~ @disk_only_regex)
|
193
|
+
[]
|
194
|
+
else
|
195
|
+
plot_stmt = []
|
149
196
|
|
150
|
-
if @
|
151
|
-
|
152
|
-
|
153
|
-
|
197
|
+
if @disk_plot_read
|
198
|
+
plot_stmt.push("\"disk.dat\" ind #{idx} usi 1:2 with lines lw 2 title \"#{devname} read\"")
|
199
|
+
end
|
200
|
+
if @disk_plot_write
|
201
|
+
plot_stmt.push("\"disk.dat\" ind #{idx} usi 1:3 with lines lw 2 title \"#{devname} write\"")
|
154
202
|
end
|
155
203
|
|
156
|
-
|
157
|
-
devices.map{|device|
|
158
|
-
[diskinfo[device]["riops"], diskinfo[device]["wiops"],
|
159
|
-
diskinfo[device]["rkbyteps"] * 512 / 1024 / 1024, # in MB/s
|
160
|
-
diskinfo[device]["wkbyteps"] * 512 / 1024 / 1024, # in MB/s
|
161
|
-
]
|
162
|
-
}].flatten.map(&:to_s).join("\t"))
|
204
|
+
plot_stmt
|
163
205
|
end
|
206
|
+
end.flatten
|
164
207
|
|
165
|
-
|
208
|
+
total_transfer_plot_stmt_list = []
|
209
|
+
transfer_plot_stmt_list = meta["disk"]["devices"].map do |dev_entry|
|
210
|
+
devname = dev_entry["name"]
|
211
|
+
idx = dev_entry["idx"]
|
166
212
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end.flatten
|
213
|
+
if devname == "total"
|
214
|
+
if @disk_plot_read
|
215
|
+
total_transfer_plot_stmt_list.push("\"disk.dat\" ind #{idx} usi 1:4 with lines lw 2 title \"#{devname} read\"")
|
216
|
+
end
|
217
|
+
if @disk_plot_write
|
218
|
+
total_transfer_plot_stmt_list.push("\"disk.dat\" ind #{idx} usi 1:5 with lines lw 2 title \"#{devname} write\"")
|
219
|
+
end
|
175
220
|
|
176
|
-
|
177
|
-
|
221
|
+
[]
|
222
|
+
elsif @disk_only_regex && !(devname =~ @disk_only_regex)
|
223
|
+
[]
|
224
|
+
else
|
178
225
|
plot_stmt = []
|
179
|
-
|
180
|
-
|
181
|
-
|
226
|
+
|
227
|
+
if @disk_plot_read
|
228
|
+
plot_stmt.push("\"disk.dat\" ind #{idx} usi 1:4 with lines lw 2 title \"#{devname} read\"")
|
229
|
+
end
|
230
|
+
if @disk_plot_write
|
231
|
+
plot_stmt.push("\"disk.dat\" ind #{idx} usi 1:5 with lines lw 2 title \"#{devname} write\"")
|
232
|
+
end
|
233
|
+
|
182
234
|
plot_stmt
|
183
|
-
end
|
235
|
+
end
|
236
|
+
end.flatten
|
237
|
+
|
238
|
+
if iops_plot_stmt_list.size == 0
|
239
|
+
puts("No plot target disk devices.")
|
240
|
+
return
|
241
|
+
end
|
184
242
|
|
185
|
-
|
243
|
+
num_dev = meta["disk"]["devices"].select do |dev_entry|
|
244
|
+
dev_entry["name"] != "total"
|
245
|
+
end.size
|
246
|
+
|
247
|
+
if num_dev > @disk_numkey_threshold
|
248
|
+
set_key_stmt = "unset key"
|
249
|
+
else
|
250
|
+
set_key_stmt = "set key below center"
|
251
|
+
end
|
252
|
+
|
253
|
+
gpfile.puts <<EOS
|
186
254
|
set term pdfcairo enhanced color
|
187
|
-
set title "IOPS
|
255
|
+
set title "IOPS"
|
188
256
|
set size 1.0, 1.0
|
189
257
|
set output "#{iops_pdf_filename}"
|
190
258
|
|
@@ -192,54 +260,67 @@ set xlabel "elapsed time [sec]"
|
|
192
260
|
set ylabel "IOPS"
|
193
261
|
|
194
262
|
set grid
|
195
|
-
set xrange [#{@offset_time}
|
263
|
+
set xrange [#{@offset_time}:#{end_time - start_time}]
|
196
264
|
set yrange [0:*]
|
197
265
|
|
198
|
-
|
199
|
-
|
266
|
+
#{set_key_stmt}
|
200
267
|
plot #{iops_plot_stmt_list.join(",\\\n ")}
|
201
268
|
|
269
|
+
set title "Total IOPS"
|
270
|
+
unset key
|
271
|
+
set output "#{total_iops_pdf_filename}"
|
272
|
+
plot #{total_iops_plot_stmt_list.join(",\\\n ")}
|
273
|
+
|
202
274
|
|
203
|
-
set title "Transfer rate
|
275
|
+
set title "Transfer rate"
|
204
276
|
set output "#{transfer_pdf_filename}"
|
205
277
|
set ylabel "transfer rate [MB/s]"
|
278
|
+
#{set_key_stmt}
|
206
279
|
plot #{transfer_plot_stmt_list.join(",\\\n ")}
|
207
|
-
EOS
|
208
280
|
|
209
|
-
|
281
|
+
set title "Total transfer rate"
|
282
|
+
set output "#{total_transfer_pdf_filename}"
|
283
|
+
unset key
|
284
|
+
plot #{total_transfer_plot_stmt_list.join(",\\\n ")}
|
285
|
+
EOS
|
286
|
+
gpfile.close
|
210
287
|
|
211
|
-
|
288
|
+
system("gnuplot #{gpfile.path}")
|
212
289
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
290
|
+
if @output_type != 'pdf'
|
291
|
+
system("convert -density 150 -background white #{iops_pdf_filename} #{iops_img_filename}")
|
292
|
+
system("convert -density 150 -background white #{transfer_pdf_filename} #{transfer_img_filename}")
|
293
|
+
system("convert -density 150 -background white #{total_iops_pdf_filename} #{total_iops_img_filename}")
|
294
|
+
system("convert -density 150 -background white #{total_transfer_pdf_filename} #{total_transfer_img_filename}")
|
295
|
+
end
|
217
296
|
|
218
|
-
|
297
|
+
end # chdir
|
219
298
|
|
220
|
-
|
221
|
-
|
222
|
-
|
299
|
+
copy_targets = []
|
300
|
+
copy_targets += [iops_pdf_filename, transfer_pdf_filename]
|
301
|
+
copy_targets += [total_iops_pdf_filename, total_transfer_pdf_filename]
|
302
|
+
copy_targets.push(iops_img_filename) if iops_img_filename
|
303
|
+
copy_targets.push(transfer_img_filename) if transfer_img_filename
|
304
|
+
copy_targets.push(total_iops_img_filename) if total_iops_img_filename
|
305
|
+
copy_targets.push(total_transfer_img_filename) if total_transfer_img_filename
|
223
306
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
307
|
+
if @save_gpfiles
|
308
|
+
copy_targets.push(dat_filename)
|
309
|
+
copy_targets.push(gp_filename)
|
310
|
+
end
|
228
311
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
end # mktempdir
|
312
|
+
copy_targets.each do |target|
|
313
|
+
FileUtils.copy(File.join(@tmpdir, target), @output_dir)
|
314
|
+
end
|
233
315
|
end # def
|
234
316
|
|
235
|
-
def
|
317
|
+
def plot_cpu(meta)
|
236
318
|
pdf_filename = @output_prefix + 'cpu.pdf'
|
237
319
|
gp_filename = @output_prefix + 'cpu.gp'
|
238
320
|
dat_filename = @output_prefix + 'cpu.dat'
|
239
321
|
|
240
322
|
all_pdf_filename = @output_prefix + 'allcpu.pdf'
|
241
323
|
all_gp_filename = @output_prefix + 'allcpu.gp'
|
242
|
-
all_dat_filename = @output_prefix + 'allcpu.dat'
|
243
324
|
|
244
325
|
if @output_type != 'pdf'
|
245
326
|
img_filename = @output_prefix + 'cpu.' + @output_type
|
@@ -249,52 +330,27 @@ EOS
|
|
249
330
|
all_img_filename = nil
|
250
331
|
end
|
251
332
|
|
252
|
-
|
253
|
-
|
254
|
-
datafile = File.open(dat_filename, 'w')
|
255
|
-
gpfile = File.open(gp_filename, 'w')
|
256
|
-
all_datafile = File.open(all_dat_filename, 'w')
|
257
|
-
all_gpfile = File.open(all_gp_filename, 'w')
|
258
|
-
|
259
|
-
start_time = nil
|
260
|
-
end_time = 0
|
261
|
-
devices = nil
|
262
|
-
nr_cpu = nil
|
263
|
-
|
264
|
-
File.open(json_file).each_line do |line|
|
265
|
-
record = JSON.parse(line)
|
266
|
-
|
267
|
-
time = record["time"]
|
268
|
-
cpuinfo = record["cpu"]
|
269
|
-
return unless cpuinfo
|
270
|
-
nr_cpu = cpuinfo['num_core']
|
271
|
-
|
272
|
-
cores = cpuinfo['cores']
|
333
|
+
start_time = meta["start_time"]
|
334
|
+
end_time = meta["end_time"]
|
273
335
|
|
274
|
-
|
275
|
-
|
336
|
+
Dir.chdir(@tmpdir) do
|
337
|
+
gpfile = File.open(gp_filename, 'w')
|
338
|
+
all_gpfile = File.open(all_gp_filename, 'w')
|
276
339
|
|
277
|
-
|
278
|
-
|
279
|
-
cores.map{|core| core[key]}.inject(&:+)
|
280
|
-
end].flatten.map(&:to_s).join("\t"))
|
281
|
-
end
|
282
|
-
datafile.close
|
340
|
+
devices = nil
|
341
|
+
nr_cpu = meta["cpu"]["num_core"]
|
283
342
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
plot_stmt_list << plot_stmt
|
291
|
-
col_idx += 1
|
292
|
-
end
|
343
|
+
plot_stmt_list = []
|
344
|
+
%w|%usr %nice %sys %iowait %hardirq %softirq %steal %guest|.each_with_index do |key, idx|
|
345
|
+
stack_columns = (0..idx).to_a.map{|x| x + 2}
|
346
|
+
plot_stmt = "\"cpu.dat\" ind 0 usi 1:(#{stack_columns.map{|i| "$#{i}"}.join("+")}) with filledcurve x1 lw 0 lc #{idx+1} title \"#{key}\""
|
347
|
+
plot_stmt_list << plot_stmt
|
348
|
+
end
|
293
349
|
|
294
|
-
|
295
|
-
|
350
|
+
pdf_file = File.join(@output_dir, "cpu.pdf")
|
351
|
+
gpfile.puts <<EOS
|
296
352
|
set term pdfcairo enhanced color
|
297
|
-
set title "CPU usage
|
353
|
+
set title "CPU usage (max: #{nr_cpu*100}%)"
|
298
354
|
set output "#{pdf_filename}"
|
299
355
|
set key outside center bottom horizontal
|
300
356
|
set size 1.0, 1.0
|
@@ -309,24 +365,30 @@ set yrange [0:*]
|
|
309
365
|
plot #{plot_stmt_list.reverse.join(",\\\n ")}
|
310
366
|
EOS
|
311
367
|
|
312
|
-
|
313
|
-
|
368
|
+
gpfile.close
|
369
|
+
system("gnuplot #{gpfile.path}")
|
314
370
|
|
315
|
-
|
316
|
-
|
317
|
-
|
371
|
+
if @output_type != 'pdf'
|
372
|
+
system("convert -density 150 -background white #{pdf_filename} #{img_filename}")
|
373
|
+
end
|
318
374
|
|
319
|
-
|
375
|
+
## Plot all CPUs in a single file
|
320
376
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
377
|
+
nr_cpu_factors = factors(nr_cpu)
|
378
|
+
nr_cols = nr_cpu_factors.select do |x|
|
379
|
+
x <= Math.sqrt(nr_cpu)
|
380
|
+
end.max
|
381
|
+
nr_cols ||= Math.sqrt(nr_cpu).ceil
|
382
|
+
nr_rows = nr_cpu / nr_cols
|
327
383
|
|
328
|
-
|
329
|
-
|
384
|
+
plot_height = 8
|
385
|
+
|
386
|
+
if nr_rows == 1
|
387
|
+
plot_height /= 2.0
|
388
|
+
end
|
389
|
+
|
390
|
+
all_gpfile.puts <<EOS
|
391
|
+
set term pdfcairo color enhanced size 8.5inch, #{plot_height}inch
|
330
392
|
set output "#{all_pdf_filename}"
|
331
393
|
set size 1.0, 1.0
|
332
394
|
set multiplot
|
@@ -336,28 +398,19 @@ set yrange [0:101]
|
|
336
398
|
|
337
399
|
EOS
|
338
400
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
record = JSON.parse(line)
|
344
|
-
time = record["time"]
|
345
|
-
cpurec = record["cpu"]["cores"][cpu_idx]
|
346
|
-
all_datafile.puts([time - start_time,
|
347
|
-
cpurec["usr"] + cpurec["nice"],
|
348
|
-
cpurec["sys"],
|
349
|
-
cpurec["hardirq"],
|
350
|
-
cpurec["softirq"],
|
351
|
-
cpurec["steal"] + cpurec["guest"],
|
352
|
-
cpurec["iowait"]].map(&:to_s).join("\t"))
|
353
|
-
end
|
354
|
-
all_datafile.puts("")
|
355
|
-
all_datafile.puts("")
|
401
|
+
legend_height = 0.04
|
402
|
+
nr_cpu.times do |cpu_idx|
|
403
|
+
xpos = (1.0 / nr_cols) * (cpu_idx % nr_cols)
|
404
|
+
ypos = ((1.0 - legend_height) / nr_rows) * (nr_rows - 1 - (cpu_idx / nr_cols).to_i) + legend_height
|
356
405
|
|
357
|
-
|
358
|
-
|
406
|
+
plot_stmt_list = []
|
407
|
+
%w|%usr %nice %sys %iowait %hardirq %softirq %steal %guest|.each_with_index do |key, idx|
|
408
|
+
stack_columns = (0..idx).to_a.map{|x| x + 2}
|
409
|
+
plot_stmt = "\"cpu.dat\" ind #{cpu_idx+1} usi 1:(#{stack_columns.map{|i| "$#{i}"}.join("+")}) with filledcurve x1 lw 0 lc #{idx+1} title \"#{key}\""
|
410
|
+
plot_stmt_list << plot_stmt
|
411
|
+
end
|
359
412
|
|
360
|
-
|
413
|
+
all_gpfile.puts <<EOS
|
361
414
|
set title 'cpu #{cpu_idx}' offset 0.0,-0.7 font 'Arial,16'
|
362
415
|
unset key
|
363
416
|
set origin #{xpos}, #{ypos}
|
@@ -369,20 +422,20 @@ set bmargin 1.3
|
|
369
422
|
set xtics offset 0.0,0.5
|
370
423
|
set ytics offset 0.5,0
|
371
424
|
set style fill noborder
|
372
|
-
plot
|
373
|
-
'#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4+$5+$6) with filledcurve x1 lw 0 lc 5 title '%other', \\
|
374
|
-
'#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4+$5) with filledcurve x1 lw 0 lc 4 title '%soft', \\
|
375
|
-
'#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4) with filledcurve x1 lw 0 lc 3 title '%irq', \\
|
376
|
-
'#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3) with filledcurve x1 lw 0 lc 2 title '%sys', \\
|
377
|
-
'#{all_datafile.path}' index #{cpu_idx} using 1:2 with filledcurve x1 lw 0 lc 1 title '%usr'
|
425
|
+
plot #{plot_stmt_list.reverse.join(",\\\n ")}
|
378
426
|
|
379
427
|
EOS
|
428
|
+
end # times
|
380
429
|
|
381
|
-
|
382
|
-
|
383
|
-
|
430
|
+
# plot legends
|
431
|
+
plot_stmt_list = []
|
432
|
+
%w|%usr %nice %sys %iowait %hardirq %softirq %steal %guest|.each_with_index do |key, idx|
|
433
|
+
plot_stmt = "-1 with filledcurve x1 lw 0 lc #{idx+1} title \"#{key}\""
|
434
|
+
plot_stmt_list << plot_stmt
|
435
|
+
end
|
436
|
+
all_gpfile.puts <<EOS
|
384
437
|
unset title
|
385
|
-
set key center center horizontal font "Arial,
|
438
|
+
set key center center horizontal font "Arial,14"
|
386
439
|
set origin 0.0, 0.0
|
387
440
|
set size 1.0, #{legend_height}
|
388
441
|
set rmargin 0
|
@@ -394,45 +447,38 @@ set border 0
|
|
394
447
|
set yrange [0:1]
|
395
448
|
# plot -1 with filledcurve x1 title '%usr'
|
396
449
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
-1 with filledcurve x1 lw 0 lc 4 title '%soft', \\
|
401
|
-
-1 with filledcurve x1 lw 0 lc 5 title '%other', \\
|
402
|
-
-1 with filledcurve x1 lw 0 lc 6 title '%iowait'
|
450
|
+
set xlabel "elapsed time [sec]"
|
451
|
+
plot #{plot_stmt_list.reverse.join(",\\\n ")}
|
452
|
+
|
403
453
|
EOS
|
404
454
|
|
405
|
-
|
406
|
-
|
407
|
-
all_datafile.close
|
408
|
-
all_gpfile.close
|
455
|
+
all_gpfile.fsync
|
456
|
+
all_gpfile.close
|
409
457
|
|
410
|
-
|
458
|
+
system("gnuplot #{all_gpfile.path}")
|
411
459
|
|
412
|
-
|
413
|
-
|
414
|
-
|
460
|
+
if @output_type != 'pdf'
|
461
|
+
system("convert -density 150 -background white #{all_pdf_filename} #{all_img_filename}")
|
462
|
+
end
|
415
463
|
|
416
|
-
|
464
|
+
end # chdir
|
417
465
|
|
418
|
-
|
466
|
+
copy_targets = []
|
419
467
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
468
|
+
copy_targets << pdf_filename
|
469
|
+
copy_targets << img_filename if img_filename
|
470
|
+
copy_targets << all_pdf_filename
|
471
|
+
copy_targets << all_img_filename if all_img_filename
|
424
472
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
end
|
473
|
+
if @save_gpfiles
|
474
|
+
copy_targets << gp_filename
|
475
|
+
copy_targets << dat_filename
|
476
|
+
copy_targets << all_gp_filename
|
477
|
+
end
|
431
478
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
end # mktempdir
|
479
|
+
copy_targets.each do |target|
|
480
|
+
FileUtils.copy(File.join(@tmpdir, target), @output_dir)
|
481
|
+
end
|
436
482
|
end # def
|
437
483
|
|
438
484
|
private
|