0001
0002
0003
0004
0005 """ This utility can be used to debug and tune the performance of the
0006 intel_pstate driver. This utility can be used in two ways:
0007 - If there is Linux trace file with pstate_sample events enabled, then
0008 this utility can parse the trace file and generate performance plots.
0009 - If user has not specified a trace file as input via command line parameters,
0010 then this utility enables and collects trace data for a user specified interval
0011 and generates performance plots.
0012
0013 Prerequisites:
0014 Python version 2.7.x or higher
0015 gnuplot 5.0 or higher
0016 gnuplot-py 1.8 or higher
0017 (Most of the distributions have these required packages. They may be called
0018 gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... )
0019
0020 HWP (Hardware P-States are disabled)
0021 Kernel config for Linux trace is enabled
0022
0023 see print_help(): for Usage and Output details
0024
0025 """
0026 from __future__ import print_function
0027 from datetime import datetime
0028 import subprocess
0029 import os
0030 import time
0031 import re
0032 import signal
0033 import sys
0034 import getopt
0035 import Gnuplot
0036 from numpy import *
0037 from decimal import *
0038
0039 __author__ = "Srinivas Pandruvada"
0040 __copyright__ = " Copyright (c) 2017, Intel Corporation. "
0041 __license__ = "GPL version 2"
0042
0043
0044 MAX_CPUS = 256
0045
0046
0047 C_COMM = 18
0048 C_GHZ = 17
0049 C_ELAPSED = 16
0050 C_SAMPLE = 15
0051 C_DURATION = 14
0052 C_LOAD = 13
0053 C_BOOST = 12
0054 C_FREQ = 11
0055 C_TSC = 10
0056 C_APERF = 9
0057 C_MPERF = 8
0058 C_TO = 7
0059 C_FROM = 6
0060 C_SCALED = 5
0061 C_CORE = 4
0062 C_USEC = 3
0063 C_SEC = 2
0064 C_CPU = 1
0065
0066 global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname, trace_file
0067
0068
0069 getcontext().prec = 11
0070
0071 sample_num =0
0072 last_sec_cpu = [0] * MAX_CPUS
0073 last_usec_cpu = [0] * MAX_CPUS
0074
0075 def print_help(driver_name):
0076 print('%s_tracer.py:'%driver_name)
0077 print(' Usage:')
0078 print(' If the trace file is available, then to simply parse and plot, use (sudo not required):')
0079 print(' ./%s_tracer.py [-c cpus] -t <trace_file> -n <test_name>'%driver_name)
0080 print(' Or')
0081 print(' ./%s_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>'%driver_name)
0082 print(' To generate trace file, parse and plot, use (sudo required):')
0083 print(' sudo ./%s_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>'%driver_name)
0084 print(' Or')
0085 print(' sudo ./%s_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>'%driver_name)
0086 print(' Optional argument:')
0087 print(' cpus: comma separated list of CPUs')
0088 print(' kbytes: Kilo bytes of memory per CPU to allocate to the trace buffer. Default: 10240')
0089 print(' Output:')
0090 print(' If not already present, creates a "results/test_name" folder in the current working directory with:')
0091 print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.')
0092 print(' cpu???.csv - comma seperated values file for CPU number ???.')
0093 print(' *.png - a variety of PNG format plot files created from the trace contents and the additional calculations.')
0094 print(' Notes:')
0095 print(' Avoid the use of _ (underscore) in test names, because in gnuplot it is a subscript directive.')
0096 print(' Maximum number of CPUs is {0:d}. If there are more the script will abort with an error.'.format(MAX_CPUS))
0097 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.')
0098 print(' Empty y range warnings for autoscaled plots can occur and can be ignored.')
0099
0100 def plot_perf_busy_with_sample(cpu_index):
0101 """ Plot method to per cpu information """
0102
0103 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
0104 if os.path.exists(file_name):
0105 output_png = "cpu%03d_perf_busy_vs_samples.png" % cpu_index
0106 g_plot = common_all_gnuplot_settings(output_png)
0107
0108 g_plot('set y2range [0:200]')
0109 g_plot('set y2tics 0, 10')
0110 g_plot('set title "{} : cpu perf busy vs. sample : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
0111
0112 g_plot('set xlabel "Samples"')
0113 g_plot('set ylabel "P-State"')
0114 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
0115 set_4_plot_linestyles(g_plot)
0116 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_SAMPLE, C_CORE))
0117 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_SAMPLE, C_SCALED))
0118 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_SAMPLE, C_BOOST))
0119 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_SAMPLE, C_TO))
0120
0121 def plot_perf_busy(cpu_index):
0122 """ Plot some per cpu information """
0123
0124 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
0125 if os.path.exists(file_name):
0126 output_png = "cpu%03d_perf_busy.png" % cpu_index
0127 g_plot = common_all_gnuplot_settings(output_png)
0128
0129 g_plot('set y2range [0:200]')
0130 g_plot('set y2tics 0, 10')
0131 g_plot('set title "{} : perf busy : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
0132 g_plot('set ylabel "P-State"')
0133 g_plot('set y2label "Scaled Busy/performance/io-busy(%)"')
0134 set_4_plot_linestyles(g_plot)
0135 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y2 title "performance",\\'.format(C_ELAPSED, C_CORE))
0136 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 2 axis x1y2 title "scaled-busy",\\'.format(C_ELAPSED, C_SCALED))
0137 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 3 axis x1y2 title "io-boost",\\'.format(C_ELAPSED, C_BOOST))
0138 g_plot('"' + file_name + '" using {:d}:{:d} with linespoints linestyle 4 axis x1y1 title "P-State"'.format(C_ELAPSED, C_TO))
0139
0140 def plot_durations(cpu_index):
0141 """ Plot per cpu durations """
0142
0143 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
0144 if os.path.exists(file_name):
0145 output_png = "cpu%03d_durations.png" % cpu_index
0146 g_plot = common_all_gnuplot_settings(output_png)
0147
0148 g_plot('set title "{} : durations : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
0149 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
0150
0151 g_plot('set key off')
0152 set_4_plot_linestyles(g_plot)
0153 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DURATION))
0154
0155 def plot_loads(cpu_index):
0156 """ Plot per cpu loads """
0157
0158 file_name = 'cpu{:0>3}.csv'.format(cpu_index)
0159 if os.path.exists(file_name):
0160 output_png = "cpu%03d_loads.png" % cpu_index
0161 g_plot = common_all_gnuplot_settings(output_png)
0162 g_plot('set yrange [0:100]')
0163 g_plot('set ytics 0, 10')
0164 g_plot('set title "{} : loads : CPU {:0>3} : {:%F %H:%M}"'.format(testname, cpu_index, datetime.now()))
0165 g_plot('set ylabel "CPU load (percent)"')
0166
0167 g_plot('set key off')
0168 set_4_plot_linestyles(g_plot)
0169 g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
0170
0171 def plot_pstate_cpu_with_sample():
0172 """ Plot all cpu information """
0173
0174 if os.path.exists('cpu.csv'):
0175 output_png = 'all_cpu_pstates_vs_samples.png'
0176 g_plot = common_all_gnuplot_settings(output_png)
0177
0178
0179 g_plot('set xlabel "Samples"')
0180 g_plot('set ylabel "P-State"')
0181 g_plot('set title "{} : cpu pstate vs. sample : {:%F %H:%M}"'.format(testname, datetime.now()))
0182 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0183 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_SAMPLE, C_TO)
0184 g_plot('title_list = "{}"'.format(title_list))
0185 g_plot(plot_str)
0186
0187 def plot_pstate_cpu():
0188 """ Plot all cpu information from csv files """
0189
0190 output_png = 'all_cpu_pstates.png'
0191 g_plot = common_all_gnuplot_settings(output_png)
0192
0193 g_plot('set ylabel "P-State"')
0194 g_plot('set title "{} : cpu pstates : {:%F %H:%M}"'.format(testname, datetime.now()))
0195
0196
0197
0198
0199 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0200 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_TO)
0201 g_plot('title_list = "{}"'.format(title_list))
0202 g_plot(plot_str)
0203
0204 def plot_load_cpu():
0205 """ Plot all cpu loads """
0206
0207 output_png = 'all_cpu_loads.png'
0208 g_plot = common_all_gnuplot_settings(output_png)
0209 g_plot('set yrange [0:100]')
0210 g_plot('set ylabel "CPU load (percent)"')
0211 g_plot('set title "{} : cpu loads : {:%F %H:%M}"'.format(testname, datetime.now()))
0212
0213 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0214 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_LOAD)
0215 g_plot('title_list = "{}"'.format(title_list))
0216 g_plot(plot_str)
0217
0218 def plot_frequency_cpu():
0219 """ Plot all cpu frequencies """
0220
0221 output_png = 'all_cpu_frequencies.png'
0222 g_plot = common_all_gnuplot_settings(output_png)
0223
0224 g_plot('set ylabel "CPU Frequency (GHz)"')
0225 g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(testname, datetime.now()))
0226
0227 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0228 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
0229 g_plot('title_list = "{}"'.format(title_list))
0230 g_plot(plot_str)
0231
0232 def plot_duration_cpu():
0233 """ Plot all cpu durations """
0234
0235 output_png = 'all_cpu_durations.png'
0236 g_plot = common_all_gnuplot_settings(output_png)
0237
0238 g_plot('set ylabel "Timer Duration (MilliSeconds)"')
0239 g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
0240
0241 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0242 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_DURATION)
0243 g_plot('title_list = "{}"'.format(title_list))
0244 g_plot(plot_str)
0245
0246 def plot_scaled_cpu():
0247 """ Plot all cpu scaled busy """
0248
0249 output_png = 'all_cpu_scaled.png'
0250 g_plot = common_all_gnuplot_settings(output_png)
0251
0252 g_plot('set ylabel "Scaled Busy (Unitless)"')
0253 g_plot('set title "{} : cpu scaled busy : {:%F %H:%M}"'.format(testname, datetime.now()))
0254
0255 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0256 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_SCALED)
0257 g_plot('title_list = "{}"'.format(title_list))
0258 g_plot(plot_str)
0259
0260 def plot_boost_cpu():
0261 """ Plot all cpu IO Boosts """
0262
0263 output_png = 'all_cpu_boost.png'
0264 g_plot = common_all_gnuplot_settings(output_png)
0265 g_plot('set yrange [0:100]')
0266 g_plot('set ylabel "CPU IO Boost (percent)"')
0267 g_plot('set title "{} : cpu io boost : {:%F %H:%M}"'.format(testname, datetime.now()))
0268
0269 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0270 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_BOOST)
0271 g_plot('title_list = "{}"'.format(title_list))
0272 g_plot(plot_str)
0273
0274 def plot_ghz_cpu():
0275 """ Plot all cpu tsc ghz """
0276
0277 output_png = 'all_cpu_ghz.png'
0278 g_plot = common_all_gnuplot_settings(output_png)
0279
0280 g_plot('set ylabel "TSC Frequency (GHz)"')
0281 g_plot('set title "{} : cpu TSC Frequencies (Sanity check calculation) : {:%F %H:%M}"'.format(testname, datetime.now()))
0282
0283 title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
0284 plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_GHZ)
0285 g_plot('title_list = "{}"'.format(title_list))
0286 g_plot(plot_str)
0287
0288 def common_all_gnuplot_settings(output_png):
0289 """ common gnuplot settings for multiple CPUs one one graph. """
0290
0291 g_plot = common_gnuplot_settings()
0292 g_plot('set output "' + output_png + '"')
0293 return(g_plot)
0294
0295 def common_gnuplot_settings():
0296 """ common gnuplot settings. """
0297
0298 g_plot = Gnuplot.Gnuplot(persist=1)
0299
0300 g_plot('set datafile separator \",\"')
0301 g_plot('set ytics nomirror')
0302 g_plot('set xtics nomirror')
0303 g_plot('set xtics font ", 10"')
0304 g_plot('set ytics font ", 10"')
0305 g_plot('set tics out scale 1.0')
0306 g_plot('set grid')
0307 g_plot('set key out horiz')
0308 g_plot('set key bot center')
0309 g_plot('set key samplen 2 spacing .8 font ", 9"')
0310 g_plot('set term png size 1200, 600')
0311 g_plot('set title font ", 11"')
0312 g_plot('set ylabel font ", 10"')
0313 g_plot('set xlabel font ", 10"')
0314 g_plot('set xlabel offset 0, 0.5')
0315 g_plot('set xlabel "Elapsed Time (Seconds)"')
0316 return(g_plot)
0317
0318 def set_4_plot_linestyles(g_plot):
0319 """ set the linestyles used for 4 plots in 1 graphs. """
0320
0321 g_plot('set style line 1 linetype 1 linecolor rgb "green" pointtype -1')
0322 g_plot('set style line 2 linetype 1 linecolor rgb "red" pointtype -1')
0323 g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
0324 g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
0325
0326 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, cpu_mask):
0327 """ Store master csv file information """
0328
0329 global graph_data_present
0330
0331 if cpu_mask[cpu_int] == 0:
0332 return
0333
0334 try:
0335 f_handle = open('cpu.csv', 'a')
0336 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)
0337 f_handle.write(string_buffer);
0338 f_handle.close()
0339 except:
0340 print('IO error cpu.csv')
0341 return
0342
0343 graph_data_present = True;
0344
0345 def split_csv(current_max_cpu, cpu_mask):
0346 """ seperate the all csv file into per CPU csv files. """
0347
0348 if os.path.exists('cpu.csv'):
0349 for index in range(0, current_max_cpu + 1):
0350 if cpu_mask[int(index)] != 0:
0351 os.system('grep -m 1 common_cpu cpu.csv > cpu{:0>3}.csv'.format(index))
0352 os.system('grep CPU_{:0>3} cpu.csv >> cpu{:0>3}.csv'.format(index, index))
0353
0354 def fix_ownership(path):
0355 """Change the owner of the file to SUDO_UID, if required"""
0356
0357 uid = os.environ.get('SUDO_UID')
0358 gid = os.environ.get('SUDO_GID')
0359 if uid is not None:
0360 os.chown(path, int(uid), int(gid))
0361
0362 def cleanup_data_files():
0363 """ clean up existing data files """
0364
0365 if os.path.exists('cpu.csv'):
0366 os.remove('cpu.csv')
0367 f_handle = open('cpu.csv', 'a')
0368 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')
0369 f_handle.write('\n')
0370 f_handle.close()
0371
0372 def clear_trace_file():
0373 """ Clear trace file """
0374
0375 try:
0376 f_handle = open('/sys/kernel/debug/tracing/trace', 'w')
0377 f_handle.close()
0378 except:
0379 print('IO error clearing trace file ')
0380 sys.exit(2)
0381
0382 def enable_trace(trace_file):
0383 """ Enable trace """
0384
0385 try:
0386 open(trace_file,'w').write("1")
0387 except:
0388 print('IO error enabling trace ')
0389 sys.exit(2)
0390
0391 def disable_trace(trace_file):
0392 """ Disable trace """
0393
0394 try:
0395 open(trace_file, 'w').write("0")
0396 except:
0397 print('IO error disabling trace ')
0398 sys.exit(2)
0399
0400 def set_trace_buffer_size(memory):
0401 """ Set trace buffer size """
0402
0403 try:
0404 with open('/sys/kernel/debug/tracing/buffer_size_kb', 'w') as fp:
0405 fp.write(memory)
0406 except:
0407 print('IO error setting trace buffer size ')
0408 sys.exit(2)
0409
0410 def free_trace_buffer():
0411 """ Free the trace buffer memory """
0412
0413 try:
0414 open('/sys/kernel/debug/tracing/buffer_size_kb'
0415 , 'w').write("1")
0416 except:
0417 print('IO error freeing trace buffer ')
0418 sys.exit(2)
0419
0420 def read_trace_data(filename, cpu_mask):
0421 """ Read and parse trace data """
0422
0423 global current_max_cpu
0424 global sample_num, last_sec_cpu, last_usec_cpu, start_time
0425
0426 try:
0427 data = open(filename, 'r').read()
0428 except:
0429 print('Error opening ', filename)
0430 sys.exit(2)
0431
0432 for line in data.splitlines():
0433 search_obj = \
0434 re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?core_busy=)(\d+)(.*?scaled=)(\d+)(.*?from=)(\d+)(.*?to=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)(.*?freq=)(\d+)'
0435 , line)
0436
0437 if search_obj:
0438 cpu = search_obj.group(3)
0439 cpu_int = int(cpu)
0440 cpu = str(cpu_int)
0441
0442 time_pre_dec = search_obj.group(6)
0443 time_post_dec = search_obj.group(8)
0444 core_busy = search_obj.group(10)
0445 scaled = search_obj.group(12)
0446 _from = search_obj.group(14)
0447 _to = search_obj.group(16)
0448 mperf = search_obj.group(18)
0449 aperf = search_obj.group(20)
0450 tsc = search_obj.group(22)
0451 freq = search_obj.group(24)
0452 common_comm = search_obj.group(2).replace(' ', '')
0453
0454
0455 io_boost = '0'
0456 search_obj = re.search(r'.*?io_boost=(\d+)', line)
0457 if search_obj:
0458 io_boost = search_obj.group(1)
0459
0460 if sample_num == 0 :
0461 start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
0462 sample_num += 1
0463
0464 if last_sec_cpu[cpu_int] == 0 :
0465 last_sec_cpu[cpu_int] = time_pre_dec
0466 last_usec_cpu[cpu_int] = time_post_dec
0467 else :
0468 duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
0469 duration_ms = Decimal(duration_us) / Decimal(1000)
0470 last_sec_cpu[cpu_int] = time_pre_dec
0471 last_usec_cpu[cpu_int] = time_post_dec
0472 elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
0473 load = Decimal(int(mperf)*100)/ Decimal(tsc)
0474 freq_ghz = Decimal(freq)/Decimal(1000000)
0475
0476
0477 tsc_ghz = Decimal(0)
0478 if duration_ms != Decimal(0) :
0479 tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
0480 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, cpu_mask)
0481
0482 if cpu_int > current_max_cpu:
0483 current_max_cpu = cpu_int
0484
0485
0486 split_csv(current_max_cpu, cpu_mask)
0487
0488 def signal_handler(signal, frame):
0489 print(' SIGINT: Forcing cleanup before exit.')
0490 if interval:
0491 disable_trace(trace_file)
0492 clear_trace_file()
0493
0494 free_trace_buffer()
0495 sys.exit(0)
0496
0497 if __name__ == "__main__":
0498 trace_file = "/sys/kernel/debug/tracing/events/power/pstate_sample/enable"
0499 signal.signal(signal.SIGINT, signal_handler)
0500
0501 interval = ""
0502 filename = ""
0503 cpu_list = ""
0504 testname = ""
0505 memory = "10240"
0506 graph_data_present = False;
0507
0508 valid1 = False
0509 valid2 = False
0510
0511 cpu_mask = zeros((MAX_CPUS,), dtype=int)
0512
0513 try:
0514 opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
0515 except getopt.GetoptError:
0516 print_help('intel_pstate')
0517 sys.exit(2)
0518 for opt, arg in opts:
0519 if opt == '-h':
0520 print_help('intel_pstate')
0521 sys.exit()
0522 elif opt in ("-t", "--trace_file"):
0523 valid1 = True
0524 location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
0525 filename = os.path.join(location, arg)
0526 elif opt in ("-i", "--interval"):
0527 valid1 = True
0528 interval = arg
0529 elif opt in ("-c", "--cpu"):
0530 cpu_list = arg
0531 elif opt in ("-n", "--name"):
0532 valid2 = True
0533 testname = arg
0534 elif opt in ("-m", "--memory"):
0535 memory = arg
0536
0537 if not (valid1 and valid2):
0538 print_help('intel_pstate')
0539 sys.exit()
0540
0541 if cpu_list:
0542 for p in re.split("[,]", cpu_list):
0543 if int(p) < MAX_CPUS :
0544 cpu_mask[int(p)] = 1
0545 else:
0546 for i in range (0, MAX_CPUS):
0547 cpu_mask[i] = 1
0548
0549 if not os.path.exists('results'):
0550 os.mkdir('results')
0551
0552 fix_ownership('results')
0553
0554 os.chdir('results')
0555 if os.path.exists(testname):
0556 print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
0557 sys.exit()
0558 os.mkdir(testname)
0559
0560 fix_ownership(testname)
0561 os.chdir(testname)
0562
0563
0564 cur_version = sys.version_info
0565 print('python version (should be >= 2.7):')
0566 print(cur_version)
0567
0568
0569 cleanup_data_files()
0570
0571 if interval:
0572 filename = "/sys/kernel/debug/tracing/trace"
0573 clear_trace_file()
0574 set_trace_buffer_size(memory)
0575 enable_trace(trace_file)
0576 print('Sleeping for ', interval, 'seconds')
0577 time.sleep(int(interval))
0578 disable_trace(trace_file)
0579
0580 current_max_cpu = 0
0581
0582 read_trace_data(filename, cpu_mask)
0583
0584 if interval:
0585 clear_trace_file()
0586
0587 free_trace_buffer()
0588
0589 if graph_data_present == False:
0590 print('No valid data to plot')
0591 sys.exit(2)
0592
0593 for cpu_no in range(0, current_max_cpu + 1):
0594 plot_perf_busy_with_sample(cpu_no)
0595 plot_perf_busy(cpu_no)
0596 plot_durations(cpu_no)
0597 plot_loads(cpu_no)
0598
0599 plot_pstate_cpu_with_sample()
0600 plot_pstate_cpu()
0601 plot_load_cpu()
0602 plot_frequency_cpu()
0603 plot_duration_cpu()
0604 plot_scaled_cpu()
0605 plot_boost_cpu()
0606 plot_ghz_cpu()
0607
0608
0609 for root, dirs, files in os.walk('.'):
0610 for f in files:
0611 fix_ownership(f)
0612
0613 os.chdir('../../')