treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / tools / power / x86 / intel_pstate_tracer / intel_pstate_tracer.py
blob256199c7a182e5c65c9f875f77ec0074c18d52c6
1 #!/usr/bin/python
2 # SPDX-License-Identifier: GPL-2.0-only
3 # -*- coding: utf-8 -*-
5 """ This utility can be used to debug and tune the performance of the
6 intel_pstate driver. This utility can be used in two ways:
7 - If there is Linux trace file with pstate_sample events enabled, then
8 this utility can parse the trace file and generate performance plots.
9 - If user has not specified a trace file as input via command line parameters,
10 then this utility enables and collects trace data for a user specified interval
11 and generates performance plots.
13 Prerequisites:
14 Python version 2.7.x or higher
15 gnuplot 5.0 or higher
16 gnuplot-py 1.8 or higher
17 (Most of the distributions have these required packages. They may be called
18 gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... )
20 HWP (Hardware P-States are disabled)
21 Kernel config for Linux trace is enabled
23 see print_help(): for Usage and Output details
25 """
26 from __future__ import print_function
27 from datetime import datetime
28 import subprocess
29 import os
30 import time
31 import re
32 import signal
33 import sys
34 import getopt
35 import Gnuplot
36 from numpy import *
37 from decimal import *
39 __author__ = "Srinivas Pandruvada"
40 __copyright__ = " Copyright (c) 2017, Intel Corporation. "
41 __license__ = "GPL version 2"
44 MAX_CPUS = 256
46 # Define the csv file columns
47 C_COMM = 18
48 C_GHZ = 17
49 C_ELAPSED = 16
50 C_SAMPLE = 15
51 C_DURATION = 14
52 C_LOAD = 13
53 C_BOOST = 12
54 C_FREQ = 11
55 C_TSC = 10
56 C_APERF = 9
57 C_MPERF = 8
58 C_TO = 7
59 C_FROM = 6
60 C_SCALED = 5
61 C_CORE = 4
62 C_USEC = 3
63 C_SEC = 2
64 C_CPU = 1
66 global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname
68 # 11 digits covers uptime to 115 days
69 getcontext().prec = 11
71 sample_num =0
72 last_sec_cpu = [0] * MAX_CPUS
73 last_usec_cpu = [0] * MAX_CPUS
75 def print_help():
76 print('intel_pstate_tracer.py:')
77 print(' Usage:')
78 print(' If the trace file is available, then to simply parse and plot, use (sudo not required):')
79 print(' ./intel_pstate_tracer.py [-c cpus] -t <trace_file> -n <test_name>')
80 print(' Or')
81 print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
82 print(' To generate trace file, parse and plot, use (sudo required):')
83 print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>')
84 print(' Or')
85 print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>')
86 print(' Optional argument:')
87 print(' cpus: comma separated list of CPUs')
88 print(' kbytes: Kilo bytes of memory per CPU to allocate to the trace buffer. Default: 10240')
89 print(' Output:')
90 print(' If not already present, creates a "results/test_name" folder in the current working directory with:')
91 print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.')
92 print(' cpu???.csv - comma seperated values file for CPU number ???.')
93 print(' *.png - a variety of PNG format plot files created from the trace contents and the additional calculations.')
94 print(' Notes:')
95 print(' Avoid the use of _ (underscore) in test names, because in gnuplot it is a subscript directive.')
96 print(' Maximum number of CPUs is {0:d}. If there are more the script will abort with an error.'.format(MAX_CPUS))
97 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.')
98 print(' Empty y range warnings for autoscaled plots can occur and can be ignored.')
100 def plot_perf_busy_with_sample(cpu_index):
101 """ Plot method to per cpu information """
103 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
104 if os.path.exists(file_name):
105 output_png = "cpu%03d_perf_busy_vs_samples.png" % cpu_index
106 g_plot = common_all_gnuplot_settings(output_png)
107 # autoscale this one, no set y1 range
108 g_plot('set y2range [0:200]')
109 g_plot('set y2tics 0, 10')
110 g_plot('set title "{} : cpu perf busy vs. sample : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
111 # Override common
112 g_plot('set xlabel "Samples"')
113 g_plot('set ylabel "P-State"')
114 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
115 set_4_plot_linestyles(g_plot)
116 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_SAMPLE, C_CORE))
117 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_SAMPLE, C_SCALED))
118 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_SAMPLE, C_BOOST))
119 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_SAMPLE, C_TO))
121 def plot_perf_busy(cpu_index):
122 """ Plot some per cpu information """
124 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
125 if os.path.exists(file_name):
126 output_png = "cpu%03d_perf_busy.png" % cpu_index
127 g_plot = common_all_gnuplot_settings(output_png)
128 # autoscale this one, no set y1 range
129 g_plot('set y2range [0:200]')
130 g_plot('set y2tics 0, 10')
131 g_plot('set title "{} : perf busy : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
132 g_plot('set ylabel "P-State"')
133 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
134 set_4_plot_linestyles(g_plot)
135 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_ELAPSED, C_CORE))
136 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_ELAPSED, C_SCALED))
137 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_ELAPSED, C_BOOST))
138 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_ELAPSED, C_TO))
140 def plot_durations(cpu_index):
141 """ Plot per cpu durations """
143 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
144 if os.path.exists(file_name):
145 output_png = "cpu%03d_durations.png" % cpu_index
146 g_plot = common_all_gnuplot_settings(output_png)
147 # autoscale this one, no set y range
148 g_plot('set title "{} : durations : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
149 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
150 # override common
151 g_plot('set key off')
152 set_4_plot_linestyles(g_plot)
153 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DURATION))
155 def plot_loads(cpu_index):
156 """ Plot per cpu loads """
158 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
159 if os.path.exists(file_name):
160 output_png = "cpu%03d_loads.png" % cpu_index
161 g_plot = common_all_gnuplot_settings(output_png)
162 g_plot('set yrange [0:100]')
163 g_plot('set ytics 0, 10')
164 g_plot('set title "{} : loads : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
165 g_plot('set ylabel "CPU load (percent)"')
166 # override common
167 g_plot('set key off')
168 set_4_plot_linestyles(g_plot)
169 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
171 def plot_pstate_cpu_with_sample():
172 """ Plot all cpu information """
174 if os.path.exists('cpu.csv'):
175 output_png = 'all_cpu_pstates_vs_samples.png'
176 g_plot = common_all_gnuplot_settings(output_png)
177 # autoscale this one, no set y range
178 # override common
179 g_plot('set xlabel "Samples"')
180 g_plot('set ylabel "P-State"')
181 g_plot('set title "{} : cpu pstate vs. sample : {:%F %H:%M}"'.format(testname, datetime.now()))
182 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
183 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_SAMPLE, C_TO)
184 g_plot('title_list = "{}"'.format(title_list))
185 g_plot(plot_str)
187 def plot_pstate_cpu():
188 """ Plot all cpu information from csv files """
190 output_png = 'all_cpu_pstates.png'
191 g_plot = common_all_gnuplot_settings(output_png)
192 # autoscale this one, no set y range
193 g_plot('set ylabel "P-State"')
194 g_plot('set title "{} : cpu pstates : {:%F %H:%M}"'.format(testname, datetime.now()))
196 # the following command is really cool, but doesn't work with the CPU masking option because it aborts on the first missing file.
197 # 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'
199 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
200 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_TO)
201 g_plot('title_list = "{}"'.format(title_list))
202 g_plot(plot_str)
204 def plot_load_cpu():
205 """ Plot all cpu loads """
207 output_png = 'all_cpu_loads.png'
208 g_plot = common_all_gnuplot_settings(output_png)
209 g_plot('set yrange [0:100]')
210 g_plot('set ylabel "CPU load (percent)"')
211 g_plot('set title "{} : cpu loads : {:%F %H:%M}"'.format(testname, datetime.now()))
213 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
214 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_LOAD)
215 g_plot('title_list = "{}"'.format(title_list))
216 g_plot(plot_str)
218 def plot_frequency_cpu():
219 """ Plot all cpu frequencies """
221 output_png = 'all_cpu_frequencies.png'
222 g_plot = common_all_gnuplot_settings(output_png)
223 # autoscale this one, no set y range
224 g_plot('set ylabel "CPU Frequency (GHz)"')
225 g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(testname, datetime.now()))
227 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
228 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
229 g_plot('title_list = "{}"'.format(title_list))
230 g_plot(plot_str)
232 def plot_duration_cpu():
233 """ Plot all cpu durations """
235 output_png = 'all_cpu_durations.png'
236 g_plot = common_all_gnuplot_settings(output_png)
237 # autoscale this one, no set y range
238 g_plot('set ytics 0, 500')
239 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
240 g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
242 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
243 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_DURATION)
244 g_plot('title_list = "{}"'.format(title_list))
245 g_plot(plot_str)
247 def plot_scaled_cpu():
248 """ Plot all cpu scaled busy """
250 output_png = 'all_cpu_scaled.png'
251 g_plot = common_all_gnuplot_settings(output_png)
252 # autoscale this one, no set y range
253 g_plot('set ylabel "Scaled Busy (Unitless)"')
254 g_plot('set title "{} : cpu scaled busy : {:%F %H:%M}"'.format(testname, datetime.now()))
256 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
257 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_SCALED)
258 g_plot('title_list = "{}"'.format(title_list))
259 g_plot(plot_str)
261 def plot_boost_cpu():
262 """ Plot all cpu IO Boosts """
264 output_png = 'all_cpu_boost.png'
265 g_plot = common_all_gnuplot_settings(output_png)
266 g_plot('set yrange [0:100]')
267 g_plot('set ylabel "CPU IO Boost (percent)"')
268 g_plot('set title "{} : cpu io boost : {:%F %H:%M}"'.format(testname, datetime.now()))
270 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
271 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_BOOST)
272 g_plot('title_list = "{}"'.format(title_list))
273 g_plot(plot_str)
275 def plot_ghz_cpu():
276 """ Plot all cpu tsc ghz """
278 output_png = 'all_cpu_ghz.png'
279 g_plot = common_all_gnuplot_settings(output_png)
280 # autoscale this one, no set y range
281 g_plot('set ylabel "TSC Frequency (GHz)"')
282 g_plot('set title "{} : cpu TSC Frequencies (Sanity check calculation) : {:%F %H:%M}"'.format(testname, datetime.now()))
284 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
285 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_GHZ)
286 g_plot('title_list = "{}"'.format(title_list))
287 g_plot(plot_str)
289 def common_all_gnuplot_settings(output_png):
290 """ common gnuplot settings for multiple CPUs one one graph. """
292 g_plot = common_gnuplot_settings()
293 g_plot('set output "' + output_png + '"')
294 return(g_plot)
296 def common_gnuplot_settings():
297 """ common gnuplot settings. """
299 g_plot = Gnuplot.Gnuplot(persist=1)
300 # The following line is for rigor only. It seems to be assumed for .csv files
301 g_plot('set datafile separator \",\"')
302 g_plot('set ytics nomirror')
303 g_plot('set xtics nomirror')
304 g_plot('set xtics font ", 10"')
305 g_plot('set ytics font ", 10"')
306 g_plot('set tics out scale 1.0')
307 g_plot('set grid')
308 g_plot('set key out horiz')
309 g_plot('set key bot center')
310 g_plot('set key samplen 2 spacing .8 font ", 9"')
311 g_plot('set term png size 1200, 600')
312 g_plot('set title font ", 11"')
313 g_plot('set ylabel font ", 10"')
314 g_plot('set xlabel font ", 10"')
315 g_plot('set xlabel offset 0, 0.5')
316 g_plot('set xlabel "Elapsed Time (Seconds)"')
317 return(g_plot)
319 def set_4_plot_linestyles(g_plot):
320 """ set the linestyles used for 4 plots in 1 graphs. """
322 g_plot('set style line 1 linetype 1 linecolor rgb "green" pointtype -1')
323 g_plot('set style line 2 linetype 1 linecolor rgb "red" pointtype -1')
324 g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
325 g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
327 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):
328 """ Store master csv file information """
330 global graph_data_present
332 if cpu_mask[cpu_int] == 0:
333 return
335 try:
336 f_handle = open('cpu.csv', 'a')
337 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)
338 f_handle.write(string_buffer);
339 f_handle.close()
340 except:
341 print('IO error cpu.csv')
342 return
344 graph_data_present = True;
346 def split_csv():
347 """ seperate the all csv file into per CPU csv files. """
349 global current_max_cpu
351 if os.path.exists('cpu.csv'):
352 for index in range(0, current_max_cpu + 1):
353 if cpu_mask[int(index)] != 0:
354 os.system('grep -m 1 common_cpu cpu.csv > cpu{:0>3}.csv'.format(index))
355 os.system('grep CPU_{:0>3} cpu.csv >> cpu{:0>3}.csv'.format(index, index))
357 def fix_ownership(path):
358 """Change the owner of the file to SUDO_UID, if required"""
360 uid = os.environ.get('SUDO_UID')
361 gid = os.environ.get('SUDO_GID')
362 if uid is not None:
363 os.chown(path, int(uid), int(gid))
365 def cleanup_data_files():
366 """ clean up existing data files """
368 if os.path.exists('cpu.csv'):
369 os.remove('cpu.csv')
370 f_handle = open('cpu.csv', 'a')
371 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')
372 f_handle.write('\n')
373 f_handle.close()
375 def clear_trace_file():
376 """ Clear trace file """
378 try:
379 f_handle = open('/sys/kernel/debug/tracing/trace', 'w')
380 f_handle.close()
381 except:
382 print('IO error clearing trace file ')
383 sys.exit(2)
385 def enable_trace():
386 """ Enable trace """
388 try:
389 open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
390 , 'w').write("1")
391 except:
392 print('IO error enabling trace ')
393 sys.exit(2)
395 def disable_trace():
396 """ Disable trace """
398 try:
399 open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
400 , 'w').write("0")
401 except:
402 print('IO error disabling trace ')
403 sys.exit(2)
405 def set_trace_buffer_size():
406 """ Set trace buffer size """
408 try:
409 with open('/sys/kernel/debug/tracing/buffer_size_kb', 'w') as fp:
410 fp.write(memory)
411 except:
412 print('IO error setting trace buffer size ')
413 sys.exit(2)
415 def free_trace_buffer():
416 """ Free the trace buffer memory """
418 try:
419 open('/sys/kernel/debug/tracing/buffer_size_kb'
420 , 'w').write("1")
421 except:
422 print('IO error freeing trace buffer ')
423 sys.exit(2)
425 def read_trace_data(filename):
426 """ Read and parse trace data """
428 global current_max_cpu
429 global sample_num, last_sec_cpu, last_usec_cpu, start_time
431 try:
432 data = open(filename, 'r').read()
433 except:
434 print('Error opening ', filename)
435 sys.exit(2)
437 for line in data.splitlines():
438 search_obj = \
439 re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?core_busy=)(\d+)(.*?scaled=)(\d+)(.*?from=)(\d+)(.*?to=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)(.*?freq=)(\d+)'
440 , line)
442 if search_obj:
443 cpu = search_obj.group(3)
444 cpu_int = int(cpu)
445 cpu = str(cpu_int)
447 time_pre_dec = search_obj.group(6)
448 time_post_dec = search_obj.group(8)
449 core_busy = search_obj.group(10)
450 scaled = search_obj.group(12)
451 _from = search_obj.group(14)
452 _to = search_obj.group(16)
453 mperf = search_obj.group(18)
454 aperf = search_obj.group(20)
455 tsc = search_obj.group(22)
456 freq = search_obj.group(24)
457 common_comm = search_obj.group(2).replace(' ', '')
459 # Not all kernel versions have io_boost field
460 io_boost = '0'
461 search_obj = re.search(r'.*?io_boost=(\d+)', line)
462 if search_obj:
463 io_boost = search_obj.group(1)
465 if sample_num == 0 :
466 start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
467 sample_num += 1
469 if last_sec_cpu[cpu_int] == 0 :
470 last_sec_cpu[cpu_int] = time_pre_dec
471 last_usec_cpu[cpu_int] = time_post_dec
472 else :
473 duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
474 duration_ms = Decimal(duration_us) / Decimal(1000)
475 last_sec_cpu[cpu_int] = time_pre_dec
476 last_usec_cpu[cpu_int] = time_post_dec
477 elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
478 load = Decimal(int(mperf)*100)/ Decimal(tsc)
479 freq_ghz = Decimal(freq)/Decimal(1000000)
480 # Sanity check calculation, typically anomalies indicate missed samples
481 # However, check for 0 (should never occur)
482 tsc_ghz = Decimal(0)
483 if duration_ms != Decimal(0) :
484 tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
485 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)
487 if cpu_int > current_max_cpu:
488 current_max_cpu = cpu_int
489 # End of for each trace line loop
490 # Now seperate the main overall csv file into per CPU csv files.
491 split_csv()
493 def signal_handler(signal, frame):
494 print(' SIGINT: Forcing cleanup before exit.')
495 if interval:
496 disable_trace()
497 clear_trace_file()
498 # Free the memory
499 free_trace_buffer()
500 sys.exit(0)
502 signal.signal(signal.SIGINT, signal_handler)
504 interval = ""
505 filename = ""
506 cpu_list = ""
507 testname = ""
508 memory = "10240"
509 graph_data_present = False;
511 valid1 = False
512 valid2 = False
514 cpu_mask = zeros((MAX_CPUS,), dtype=int)
516 try:
517 opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
518 except getopt.GetoptError:
519 print_help()
520 sys.exit(2)
521 for opt, arg in opts:
522 if opt == '-h':
523 print()
524 sys.exit()
525 elif opt in ("-t", "--trace_file"):
526 valid1 = True
527 location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
528 filename = os.path.join(location, arg)
529 elif opt in ("-i", "--interval"):
530 valid1 = True
531 interval = arg
532 elif opt in ("-c", "--cpu"):
533 cpu_list = arg
534 elif opt in ("-n", "--name"):
535 valid2 = True
536 testname = arg
537 elif opt in ("-m", "--memory"):
538 memory = arg
540 if not (valid1 and valid2):
541 print_help()
542 sys.exit()
544 if cpu_list:
545 for p in re.split("[,]", cpu_list):
546 if int(p) < MAX_CPUS :
547 cpu_mask[int(p)] = 1
548 else:
549 for i in range (0, MAX_CPUS):
550 cpu_mask[i] = 1
552 if not os.path.exists('results'):
553 os.mkdir('results')
554 # The regular user needs to own the directory, not root.
555 fix_ownership('results')
557 os.chdir('results')
558 if os.path.exists(testname):
559 print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
560 sys.exit()
561 os.mkdir(testname)
562 # The regular user needs to own the directory, not root.
563 fix_ownership(testname)
564 os.chdir(testname)
566 # Temporary (or perhaps not)
567 cur_version = sys.version_info
568 print('python version (should be >= 2.7):')
569 print(cur_version)
571 # Left as "cleanup" for potential future re-run ability.
572 cleanup_data_files()
574 if interval:
575 filename = "/sys/kernel/debug/tracing/trace"
576 clear_trace_file()
577 set_trace_buffer_size()
578 enable_trace()
579 print('Sleeping for ', interval, 'seconds')
580 time.sleep(int(interval))
581 disable_trace()
583 current_max_cpu = 0
585 read_trace_data(filename)
587 if interval:
588 clear_trace_file()
589 # Free the memory
590 free_trace_buffer()
592 if graph_data_present == False:
593 print('No valid data to plot')
594 sys.exit(2)
596 for cpu_no in range(0, current_max_cpu + 1):
597 plot_perf_busy_with_sample(cpu_no)
598 plot_perf_busy(cpu_no)
599 plot_durations(cpu_no)
600 plot_loads(cpu_no)
602 plot_pstate_cpu_with_sample()
603 plot_pstate_cpu()
604 plot_load_cpu()
605 plot_frequency_cpu()
606 plot_duration_cpu()
607 plot_scaled_cpu()
608 plot_boost_cpu()
609 plot_ghz_cpu()
611 # It is preferrable, but not necessary, that the regular user owns the files, not root.
612 for root, dirs, files in os.walk('.'):
613 for f in files:
614 fix_ownership(f)
616 os.chdir('../../')