Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / tools / power / x86 / intel_pstate_tracer / intel_pstate_tracer.py
blob29f50d4cfea085ed40c28e3b57c11c617730999e
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
4 """ This utility can be used to debug and tune the performance of the
5 intel_pstate driver. This utility can be used in two ways:
6 - If there is Linux trace file with pstate_sample events enabled, then
7 this utility can parse the trace file and generate performance plots.
8 - If user has not specified a trace file as input via command line parameters,
9 then this utility enables and collects trace data for a user specified interval
10 and generates performance plots.
12 Prerequisites:
13 Python version 2.7.x
14 gnuplot 5.0 or higher
15 gnuplot-py 1.8
16 (Most of the distributions have these required packages. They may be called
17 gnuplot-py, phython-gnuplot. )
19 HWP (Hardware P-States are disabled)
20 Kernel config for Linux trace is enabled
22 see print_help(): for Usage and Output details
24 """
25 from __future__ import print_function
26 from datetime import datetime
27 import subprocess
28 import os
29 import time
30 import re
31 import sys
32 import getopt
33 import Gnuplot
34 from numpy import *
35 from decimal import *
37 __author__ = "Srinivas Pandruvada"
38 __copyright__ = " Copyright (c) 2017, Intel Corporation. "
39 __license__ = "GPL version 2"
42 MAX_CPUS = 256
44 # Define the csv file columns
45 C_COMM = 18
46 C_GHZ = 17
47 C_ELAPSED = 16
48 C_SAMPLE = 15
49 C_DURATION = 14
50 C_LOAD = 13
51 C_BOOST = 12
52 C_FREQ = 11
53 C_TSC = 10
54 C_APERF = 9
55 C_MPERF = 8
56 C_TO = 7
57 C_FROM = 6
58 C_SCALED = 5
59 C_CORE = 4
60 C_USEC = 3
61 C_SEC = 2
62 C_CPU = 1
64 global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname
66 # 11 digits covers uptime to 115 days
67 getcontext().prec = 11
69 sample_num =0
70 last_sec_cpu = [0] * MAX_CPUS
71 last_usec_cpu = [0] * MAX_CPUS
73 def print_help():
74 print('intel_pstate_tracer.py:')
75 print(' Usage:')
76 print(' If the trace file is available, then to simply parse and plot, use (sudo not required):')
77 print(' ./intel_pstate_tracer.py [-c cpus] -t <trace_file> -n <test_name>')
78 print(' Or')
79 print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
80 print(' To generate trace file, parse and plot, use (sudo required):')
81 print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name>')
82 print(' Or')
83 print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name>')
84 print(' Optional argument:')
85 print(' cpus: comma separated list of CPUs')
86 print(' Output:')
87 print(' If not already present, creates a "results/test_name" folder in the current working directory with:')
88 print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.')
89 print(' cpu???.csv - comma seperated values file for CPU number ???.')
90 print(' *.png - a variety of PNG format plot files created from the trace contents and the additional calculations.')
91 print(' Notes:')
92 print(' Avoid the use of _ (underscore) in test names, because in gnuplot it is a subscript directive.')
93 print(' Maximum number of CPUs is {0:d}. If there are more the script will abort with an error.'.format(MAX_CPUS))
94 print(' Off-line CPUs cause the script to list some warnings, and create some empty files. Use the CPU mask feature for a clean run.')
95 print(' Empty y range warnings for autoscaled plots can occur and can be ignored.')
97 def plot_perf_busy_with_sample(cpu_index):
98 """ Plot method to per cpu information """
100 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
101 if os.path.exists(file_name):
102 output_png = "cpu%03d_perf_busy_vs_samples.png" % cpu_index
103 g_plot = common_all_gnuplot_settings(output_png)
104 g_plot('set yrange [0:40]')
105 g_plot('set y2range [0:200]')
106 g_plot('set y2tics 0, 10')
107 g_plot('set title "{} : cpu perf busy vs. sample : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
108 # Override common
109 g_plot('set xlabel "Samples"')
110 g_plot('set ylabel "P-State"')
111 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
112 set_4_plot_linestyles(g_plot)
113 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_SAMPLE, C_CORE))
114 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_SAMPLE, C_SCALED))
115 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_SAMPLE, C_BOOST))
116 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_SAMPLE, C_TO))
118 def plot_perf_busy(cpu_index):
119 """ Plot some per cpu information """
121 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
122 if os.path.exists(file_name):
123 output_png = "cpu%03d_perf_busy.png" % cpu_index
124 g_plot = common_all_gnuplot_settings(output_png)
125 g_plot('set yrange [0:40]')
126 g_plot('set y2range [0:200]')
127 g_plot('set y2tics 0, 10')
128 g_plot('set title "{} : perf busy : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
129 g_plot('set ylabel "P-State"')
130 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
131 set_4_plot_linestyles(g_plot)
132 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_ELAPSED, C_CORE))
133 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_ELAPSED, C_SCALED))
134 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_ELAPSED, C_BOOST))
135 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_ELAPSED, C_TO))
137 def plot_durations(cpu_index):
138 """ Plot per cpu durations """
140 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
141 if os.path.exists(file_name):
142 output_png = "cpu%03d_durations.png" % cpu_index
143 g_plot = common_all_gnuplot_settings(output_png)
144 # Should autoscale be used here? Should seconds be used here?
145 g_plot('set yrange [0:5000]')
146 g_plot('set ytics 0, 500')
147 g_plot('set title "{} : durations : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
148 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
149 # override common
150 g_plot('set key off')
151 set_4_plot_linestyles(g_plot)
152 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DURATION))
154 def plot_loads(cpu_index):
155 """ Plot per cpu loads """
157 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
158 if os.path.exists(file_name):
159 output_png = "cpu%03d_loads.png" % cpu_index
160 g_plot = common_all_gnuplot_settings(output_png)
161 g_plot('set yrange [0:100]')
162 g_plot('set ytics 0, 10')
163 g_plot('set title "{} : loads : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
164 g_plot('set ylabel "CPU load (percent)"')
165 # override common
166 g_plot('set key off')
167 set_4_plot_linestyles(g_plot)
168 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
170 def plot_pstate_cpu_with_sample():
171 """ Plot all cpu information """
173 if os.path.exists('cpu.csv'):
174 output_png = 'all_cpu_pstates_vs_samples.png'
175 g_plot = common_all_gnuplot_settings(output_png)
176 g_plot('set yrange [0:40]')
177 # override common
178 g_plot('set xlabel "Samples"')
179 g_plot('set ylabel "P-State"')
180 g_plot('set title "{} : cpu pstate vs. sample : {:%F %H:%M}"'.format(testname, datetime.now()))
181 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
182 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_SAMPLE, C_TO)
183 g_plot('title_list = "{}"'.format(title_list))
184 g_plot(plot_str)
186 def plot_pstate_cpu():
187 """ Plot all cpu information from csv files """
189 output_png = 'all_cpu_pstates.png'
190 g_plot = common_all_gnuplot_settings(output_png)
191 g_plot('set yrange [0:40]')
192 g_plot('set ylabel "P-State"')
193 g_plot('set title "{} : cpu pstates : {:%F %H:%M}"'.format(testname, datetime.now()))
195 # the following command is really cool, but doesn't work with the CPU masking option because it aborts on the first missing file.
196 # plot_str = 'plot for [i=0:*] file=sprintf("cpu%03d.csv",i) title_s=sprintf("cpu%03d",i) file using 16:7 pt 7 ps 1 title title_s'
198 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
199 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_TO)
200 g_plot('title_list = "{}"'.format(title_list))
201 g_plot(plot_str)
203 def plot_load_cpu():
204 """ Plot all cpu loads """
206 output_png = 'all_cpu_loads.png'
207 g_plot = common_all_gnuplot_settings(output_png)
208 g_plot('set yrange [0:100]')
209 g_plot('set ylabel "CPU load (percent)"')
210 g_plot('set title "{} : cpu loads : {:%F %H:%M}"'.format(testname, datetime.now()))
212 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
213 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_LOAD)
214 g_plot('title_list = "{}"'.format(title_list))
215 g_plot(plot_str)
217 def plot_frequency_cpu():
218 """ Plot all cpu frequencies """
220 output_png = 'all_cpu_frequencies.png'
221 g_plot = common_all_gnuplot_settings(output_png)
222 g_plot('set yrange [0:4]')
223 g_plot('set ylabel "CPU Frequency (GHz)"')
224 g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(testname, datetime.now()))
226 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
227 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
228 g_plot('title_list = "{}"'.format(title_list))
229 g_plot(plot_str)
231 def plot_duration_cpu():
232 """ Plot all cpu durations """
234 output_png = 'all_cpu_durations.png'
235 g_plot = common_all_gnuplot_settings(output_png)
236 g_plot('set yrange [0:5000]')
237 g_plot('set ytics 0, 500')
238 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
239 g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
241 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
242 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_DURATION)
243 g_plot('title_list = "{}"'.format(title_list))
244 g_plot(plot_str)
246 def plot_scaled_cpu():
247 """ Plot all cpu scaled busy """
249 output_png = 'all_cpu_scaled.png'
250 g_plot = common_all_gnuplot_settings(output_png)
251 # autoscale this one, no set y range
252 g_plot('set ylabel "Scaled Busy (Unitless)"')
253 g_plot('set title "{} : cpu scaled busy : {:%F %H:%M}"'.format(testname, datetime.now()))
255 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
256 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_SCALED)
257 g_plot('title_list = "{}"'.format(title_list))
258 g_plot(plot_str)
260 def plot_boost_cpu():
261 """ Plot all cpu IO Boosts """
263 output_png = 'all_cpu_boost.png'
264 g_plot = common_all_gnuplot_settings(output_png)
265 g_plot('set yrange [0:100]')
266 g_plot('set ylabel "CPU IO Boost (percent)"')
267 g_plot('set title "{} : cpu io boost : {:%F %H:%M}"'.format(testname, datetime.now()))
269 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
270 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_BOOST)
271 g_plot('title_list = "{}"'.format(title_list))
272 g_plot(plot_str)
274 def plot_ghz_cpu():
275 """ Plot all cpu tsc ghz """
277 output_png = 'all_cpu_ghz.png'
278 g_plot = common_all_gnuplot_settings(output_png)
279 # autoscale this one, no set y range
280 g_plot('set ylabel "TSC Frequency (GHz)"')
281 g_plot('set title "{} : cpu TSC Frequencies (Sanity check calculation) : {:%F %H:%M}"'.format(testname, datetime.now()))
283 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).replace('\n', ' ')
284 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_GHZ)
285 g_plot('title_list = "{}"'.format(title_list))
286 g_plot(plot_str)
288 def common_all_gnuplot_settings(output_png):
289 """ common gnuplot settings for multiple CPUs one one graph. """
291 g_plot = common_gnuplot_settings()
292 g_plot('set output "' + output_png + '"')
293 return(g_plot)
295 def common_gnuplot_settings():
296 """ common gnuplot settings. """
298 g_plot = Gnuplot.Gnuplot(persist=1)
299 # The following line is for rigor only. It seems to be assumed for .csv files
300 g_plot('set datafile separator \",\"')
301 g_plot('set ytics nomirror')
302 g_plot('set xtics nomirror')
303 g_plot('set xtics font ", 10"')
304 g_plot('set ytics font ", 10"')
305 g_plot('set tics out scale 1.0')
306 g_plot('set grid')
307 g_plot('set key out horiz')
308 g_plot('set key bot center')
309 g_plot('set key samplen 2 spacing .8 font ", 9"')
310 g_plot('set term png size 1200, 600')
311 g_plot('set title font ", 11"')
312 g_plot('set ylabel font ", 10"')
313 g_plot('set xlabel font ", 10"')
314 g_plot('set xlabel offset 0, 0.5')
315 g_plot('set xlabel "Elapsed Time (Seconds)"')
316 return(g_plot)
318 def set_4_plot_linestyles(g_plot):
319 """ set the linestyles used for 4 plots in 1 graphs. """
321 g_plot('set style line 1 linetype 1 linecolor rgb "green" pointtype -1')
322 g_plot('set style line 2 linetype 1 linecolor rgb "red" pointtype -1')
323 g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
324 g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
326 def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz):
327 """ Store master csv file information """
329 global graph_data_present
331 if cpu_mask[cpu_int] == 0:
332 return
334 try:
335 f_handle = open('cpu.csv', 'a')
336 string_buffer = "CPU_%03u, %05u, %06u, %u, %u, %u, %u, %u, %u, %u, %.4f, %u, %.2f, %.3f, %u, %.3f, %.3f, %s\n" % (cpu_int, int(time_pre_dec), int(time_post_dec), int(core_busy), int(scaled), int(_from), int(_to), int(mperf), int(aperf), int(tsc), freq_ghz, int(io_boost), load, duration_ms, sample_num, elapsed_time, tsc_ghz, common_comm)
337 f_handle.write(string_buffer);
338 f_handle.close()
339 except:
340 print('IO error cpu.csv')
341 return
343 graph_data_present = True;
345 def split_csv():
346 """ seperate the all csv file into per CPU csv files. """
348 global current_max_cpu
350 if os.path.exists('cpu.csv'):
351 for index in range(0, current_max_cpu + 1):
352 if cpu_mask[int(index)] != 0:
353 os.system('grep -m 1 common_cpu cpu.csv > cpu{:0>3}.csv'.format(index))
354 os.system('grep CPU_{:0>3} cpu.csv >> cpu{:0>3}.csv'.format(index, index))
356 def fix_ownership(path):
357 """Change the owner of the file to SUDO_UID, if required"""
359 uid = os.environ.get('SUDO_UID')
360 gid = os.environ.get('SUDO_GID')
361 if uid is not None:
362 os.chown(path, int(uid), int(gid))
364 def cleanup_data_files():
365 """ clean up existing data files """
367 if os.path.exists('cpu.csv'):
368 os.remove('cpu.csv')
369 f_handle = open('cpu.csv', 'a')
370 f_handle.write('common_cpu, common_secs, common_usecs, core_busy, scaled_busy, from, to, mperf, aperf, tsc, freq, boost, load, duration_ms, sample_num, elapsed_time, tsc_ghz, common_comm')
371 f_handle.write('\n')
372 f_handle.close()
374 def clear_trace_file():
375 """ Clear trace file """
377 try:
378 f_handle = open('/sys/kernel/debug/tracing/trace', 'w')
379 f_handle.close()
380 except:
381 print('IO error clearing trace file ')
382 quit()
384 def enable_trace():
385 """ Enable trace """
387 try:
388 open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
389 , 'w').write("1")
390 except:
391 print('IO error enabling trace ')
392 quit()
394 def disable_trace():
395 """ Disable trace """
397 try:
398 open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
399 , 'w').write("0")
400 except:
401 print('IO error disabling trace ')
402 quit()
404 def set_trace_buffer_size():
405 """ Set trace buffer size """
407 try:
408 open('/sys/kernel/debug/tracing/buffer_size_kb'
409 , 'w').write("10240")
410 except:
411 print('IO error setting trace buffer size ')
412 quit()
414 def free_trace_buffer():
415 """ Free the trace buffer memory """
417 try:
418 open('/sys/kernel/debug/tracing/buffer_size_kb'
419 , 'w').write("1")
420 except:
421 print('IO error setting trace buffer size ')
422 quit()
424 def read_trace_data(filename):
425 """ Read and parse trace data """
427 global current_max_cpu
428 global sample_num, last_sec_cpu, last_usec_cpu, start_time
430 try:
431 data = open(filename, 'r').read()
432 except:
433 print('Error opening ', filename)
434 quit()
436 for line in data.splitlines():
437 search_obj = \
438 re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?core_busy=)(\d+)(.*?scaled=)(\d+)(.*?from=)(\d+)(.*?to=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)(.*?freq=)(\d+)'
439 , line)
441 if search_obj:
442 cpu = search_obj.group(3)
443 cpu_int = int(cpu)
444 cpu = str(cpu_int)
446 time_pre_dec = search_obj.group(6)
447 time_post_dec = search_obj.group(8)
448 core_busy = search_obj.group(10)
449 scaled = search_obj.group(12)
450 _from = search_obj.group(14)
451 _to = search_obj.group(16)
452 mperf = search_obj.group(18)
453 aperf = search_obj.group(20)
454 tsc = search_obj.group(22)
455 freq = search_obj.group(24)
456 common_comm = search_obj.group(2).replace(' ', '')
458 # Not all kernel versions have io_boost field
459 io_boost = '0'
460 search_obj = re.search(r'.*?io_boost=(\d+)', line)
461 if search_obj:
462 io_boost = search_obj.group(1)
464 if sample_num == 0 :
465 start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
466 sample_num += 1
468 if last_sec_cpu[cpu_int] == 0 :
469 last_sec_cpu[cpu_int] = time_pre_dec
470 last_usec_cpu[cpu_int] = time_post_dec
471 else :
472 duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
473 duration_ms = Decimal(duration_us) / Decimal(1000)
474 last_sec_cpu[cpu_int] = time_pre_dec
475 last_usec_cpu[cpu_int] = time_post_dec
476 elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
477 load = Decimal(int(mperf)*100)/ Decimal(tsc)
478 freq_ghz = Decimal(freq)/Decimal(1000000)
479 # Sanity check calculation, typically anomalies indicate missed samples
480 # However, check for 0 (should never occur)
481 tsc_ghz = Decimal(0)
482 if duration_ms != Decimal(0) :
483 tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
484 store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz)
486 if cpu_int > current_max_cpu:
487 current_max_cpu = cpu_int
488 # End of for each trace line loop
489 # Now seperate the main overall csv file into per CPU csv files.
490 split_csv()
492 interval = ""
493 filename = ""
494 cpu_list = ""
495 testname = ""
496 graph_data_present = False;
498 valid1 = False
499 valid2 = False
501 cpu_mask = zeros((MAX_CPUS,), dtype=int)
503 try:
504 opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:",["help","trace_file=","interval=","cpu=","name="])
505 except getopt.GetoptError:
506 print_help()
507 sys.exit(2)
508 for opt, arg in opts:
509 if opt == '-h':
510 print()
511 sys.exit()
512 elif opt in ("-t", "--trace_file"):
513 valid1 = True
514 location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
515 filename = os.path.join(location, arg)
516 elif opt in ("-i", "--interval"):
517 valid1 = True
518 interval = arg
519 elif opt in ("-c", "--cpu"):
520 cpu_list = arg
521 elif opt in ("-n", "--name"):
522 valid2 = True
523 testname = arg
525 if not (valid1 and valid2):
526 print_help()
527 sys.exit()
529 if cpu_list:
530 for p in re.split("[,]", cpu_list):
531 if int(p) < MAX_CPUS :
532 cpu_mask[int(p)] = 1
533 else:
534 for i in range (0, MAX_CPUS):
535 cpu_mask[i] = 1
537 if not os.path.exists('results'):
538 os.mkdir('results')
539 # The regular user needs to own the directory, not root.
540 fix_ownership('results')
542 os.chdir('results')
543 if os.path.exists(testname):
544 print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
545 sys.exit()
546 os.mkdir(testname)
547 # The regular user needs to own the directory, not root.
548 fix_ownership(testname)
549 os.chdir(testname)
551 # Temporary (or perhaps not)
552 cur_version = sys.version_info
553 print('python version (should be >= 2.7):')
554 print(cur_version)
556 # Left as "cleanup" for potential future re-run ability.
557 cleanup_data_files()
559 if interval:
560 filename = "/sys/kernel/debug/tracing/trace"
561 clear_trace_file()
562 set_trace_buffer_size()
563 enable_trace()
564 print('Sleeping for ', interval, 'seconds')
565 time.sleep(int(interval))
566 disable_trace()
568 current_max_cpu = 0
570 read_trace_data(filename)
572 if graph_data_present == False:
573 print('No valid data to plot')
574 sys.exit(2)
576 for cpu_no in range(0, current_max_cpu + 1):
577 plot_perf_busy_with_sample(cpu_no)
578 plot_perf_busy(cpu_no)
579 plot_durations(cpu_no)
580 plot_loads(cpu_no)
582 plot_pstate_cpu_with_sample()
583 plot_pstate_cpu()
584 plot_load_cpu()
585 plot_frequency_cpu()
586 plot_duration_cpu()
587 plot_scaled_cpu()
588 plot_boost_cpu()
589 plot_ghz_cpu()
591 # It is preferrable, but not necessary, that the regular user owns the files, not root.
592 for root, dirs, files in os.walk('.'):
593 for f in files:
594 fix_ownership(f)
596 clear_trace_file()
597 # Free the memory
598 if interval:
599 free_trace_buffer()
601 os.chdir('../../')