~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/usr/bin/env python3
  2 # SPDX-License-Identifier: GPL-2.0-only
  3 # -*- coding: utf-8 -*-
  4 #
  5 """ This utility can be used to debug and tune the performance of the
  6 AMD P-State driver. It imports intel_pstate_tracer to analyze AMD P-State
  7 trace event.
  8 
  9 Prerequisites:
 10     Python version 2.7.x or higher
 11     gnuplot 5.0 or higher
 12     gnuplot-py 1.8 or higher
 13     (Most of the distributions have these required packages. They may be called
 14      gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... )
 15 
 16     Kernel config for Linux trace is enabled
 17 
 18     see print_help(): for Usage and Output details
 19 
 20 """
 21 from __future__ import print_function
 22 from datetime import datetime
 23 import subprocess
 24 import os
 25 import time
 26 import re
 27 import signal
 28 import sys
 29 import getopt
 30 import Gnuplot
 31 from numpy import *
 32 from decimal import *
 33 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "intel_pstate_tracer"))
 34 import intel_pstate_tracer as ipt
 35 
 36 __license__ = "GPL version 2"
 37 
 38 MAX_CPUS = 256
 39 # Define the csv file columns
 40 C_COMM = 15
 41 C_ELAPSED = 14
 42 C_SAMPLE = 13
 43 C_DURATION = 12
 44 C_LOAD = 11
 45 C_TSC = 10
 46 C_APERF = 9
 47 C_MPERF = 8
 48 C_FREQ = 7
 49 C_MAX_PERF = 6
 50 C_DES_PERF = 5
 51 C_MIN_PERF = 4
 52 C_USEC = 3
 53 C_SEC = 2
 54 C_CPU = 1
 55 
 56 global sample_num, last_sec_cpu, last_usec_cpu, start_time, test_name, trace_file
 57 
 58 getcontext().prec = 11
 59 
 60 sample_num =0
 61 last_sec_cpu = [0] * MAX_CPUS
 62 last_usec_cpu = [0] * MAX_CPUS
 63 
 64 def plot_per_cpu_freq(cpu_index):
 65     """ Plot per cpu frequency """
 66 
 67     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
 68     if os.path.exists(file_name):
 69         output_png = "cpu%03d_frequency.png" % cpu_index
 70         g_plot = ipt.common_gnuplot_settings()
 71         g_plot('set output "' + output_png + '"')
 72         g_plot('set yrange [0:7]')
 73         g_plot('set ytics 0, 1')
 74         g_plot('set ylabel "CPU Frequency (GHz)"')
 75         g_plot('set title "{} : frequency : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
 76         g_plot('set ylabel "CPU frequency"')
 77         g_plot('set key off')
 78         ipt.set_4_plot_linestyles(g_plot)
 79         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_FREQ))
 80 
 81 def plot_per_cpu_des_perf(cpu_index):
 82     """ Plot per cpu desired perf """
 83 
 84     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
 85     if os.path.exists(file_name):
 86         output_png = "cpu%03d_des_perf.png" % cpu_index
 87         g_plot = ipt.common_gnuplot_settings()
 88         g_plot('set output "' + output_png + '"')
 89         g_plot('set yrange [0:255]')
 90         g_plot('set ylabel "des perf"')
 91         g_plot('set title "{} : cpu des perf : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
 92         g_plot('set key off')
 93         ipt.set_4_plot_linestyles(g_plot)
 94         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DES_PERF))
 95 
 96 def plot_per_cpu_load(cpu_index):
 97     """ Plot per cpu load """
 98 
 99     file_name = 'cpu{:0>3}.csv'.format(cpu_index)
100     if os.path.exists(file_name):
101         output_png = "cpu%03d_load.png" % cpu_index
102         g_plot = ipt.common_gnuplot_settings()
103         g_plot('set output "' + output_png + '"')
104         g_plot('set yrange [0:100]')
105         g_plot('set ytics 0, 10')
106         g_plot('set ylabel "CPU load (percent)"')
107         g_plot('set title "{} : cpu load : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
108         g_plot('set key off')
109         ipt.set_4_plot_linestyles(g_plot)
110         g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
111 
112 def plot_all_cpu_frequency():
113     """ Plot all cpu frequencies """
114 
115     output_png = 'all_cpu_frequencies.png'
116     g_plot = ipt.common_gnuplot_settings()
117     g_plot('set output "' + output_png + '"')
118     g_plot('set ylabel "CPU Frequency (GHz)"')
119     g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(test_name, datetime.now()))
120 
121     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
122     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
123     g_plot('title_list = "{}"'.format(title_list))
124     g_plot(plot_str)
125 
126 def plot_all_cpu_des_perf():
127     """ Plot all cpu desired perf """
128 
129     output_png = 'all_cpu_des_perf.png'
130     g_plot = ipt.common_gnuplot_settings()
131     g_plot('set output "' + output_png + '"')
132     g_plot('set ylabel "des perf"')
133     g_plot('set title "{} : cpu des perf : {:%F %H:%M}"'.format(test_name, datetime.now()))
134 
135     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
136     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 255 ps 1 title i".format(C_ELAPSED, C_DES_PERF)
137     g_plot('title_list = "{}"'.format(title_list))
138     g_plot(plot_str)
139 
140 def plot_all_cpu_load():
141     """ Plot all cpu load  """
142 
143     output_png = 'all_cpu_load.png'
144     g_plot = ipt.common_gnuplot_settings()
145     g_plot('set output "' + output_png + '"')
146     g_plot('set yrange [0:100]')
147     g_plot('set ylabel "CPU load (percent)"')
148     g_plot('set title "{} : cpu load : {:%F %H:%M}"'.format(test_name, datetime.now()))
149 
150     title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
151     plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 255 ps 1 title i".format(C_ELAPSED, C_LOAD)
152     g_plot('title_list = "{}"'.format(title_list))
153     g_plot(plot_str)
154 
155 def store_csv(cpu_int, time_pre_dec, time_post_dec, min_perf, des_perf, max_perf, freq_ghz, mperf, aperf, tsc, common_comm, load, duration_ms, sample_num, elapsed_time, cpu_mask):
156     """ Store master csv file information """
157 
158     global graph_data_present
159 
160     if cpu_mask[cpu_int] == 0:
161         return
162 
163     try:
164         f_handle = open('cpu.csv', 'a')
165         string_buffer = "CPU_%03u, %05u, %06u, %u, %u, %u, %.4f, %u, %u, %u, %.2f, %.3f, %u, %.3f, %s\n" % (cpu_int, int(time_pre_dec), int(time_post_dec), int(min_perf), int(des_perf), int(max_perf), freq_ghz, int(mperf), int(aperf), int(tsc), load, duration_ms, sample_num, elapsed_time, common_comm)
166         f_handle.write(string_buffer)
167         f_handle.close()
168     except:
169         print('IO error cpu.csv')
170         return
171 
172     graph_data_present = True;
173 
174 
175 def cleanup_data_files():
176     """ clean up existing data files """
177 
178     if os.path.exists('cpu.csv'):
179         os.remove('cpu.csv')
180     f_handle = open('cpu.csv', 'a')
181     f_handle.write('common_cpu, common_secs, common_usecs, min_perf, des_perf, max_perf, freq, mperf, aperf, tsc, load, duration_ms, sample_num, elapsed_time, common_comm')
182     f_handle.write('\n')
183     f_handle.close()
184 
185 def read_trace_data(file_name, cpu_mask):
186     """ Read and parse trace data """
187 
188     global current_max_cpu
189     global sample_num, last_sec_cpu, last_usec_cpu, start_time
190 
191     try:
192         data = open(file_name, 'r').read()
193     except:
194         print('Error opening ', file_name)
195         sys.exit(2)
196 
197     for line in data.splitlines():
198         search_obj = \
199             re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?amd_min_perf=)(\d+)(.*?amd_des_perf=)(\d+)(.*?amd_max_perf=)(\d+)(.*?freq=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)'
200                       , line)
201 
202         if search_obj:
203             cpu = search_obj.group(3)
204             cpu_int = int(cpu)
205             cpu = str(cpu_int)
206 
207             time_pre_dec = search_obj.group(6)
208             time_post_dec = search_obj.group(8)
209             min_perf = search_obj.group(10)
210             des_perf = search_obj.group(12)
211             max_perf = search_obj.group(14)
212             freq = search_obj.group(16)
213             mperf = search_obj.group(18)
214             aperf = search_obj.group(20)
215             tsc = search_obj.group(22)
216 
217             common_comm = search_obj.group(2).replace(' ', '')
218 
219             if sample_num == 0 :
220                 start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
221             sample_num += 1
222 
223             if last_sec_cpu[cpu_int] == 0 :
224                 last_sec_cpu[cpu_int] = time_pre_dec
225                 last_usec_cpu[cpu_int] = time_post_dec
226             else :
227                 duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
228                 duration_ms = Decimal(duration_us) / Decimal(1000)
229                 last_sec_cpu[cpu_int] = time_pre_dec
230                 last_usec_cpu[cpu_int] = time_post_dec
231                 elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
232                 load = Decimal(int(mperf)*100)/ Decimal(tsc)
233                 freq_ghz = Decimal(freq)/Decimal(1000000)
234                 store_csv(cpu_int, time_pre_dec, time_post_dec, min_perf, des_perf, max_perf, freq_ghz, mperf, aperf, tsc, common_comm, load, duration_ms, sample_num, elapsed_time, cpu_mask)
235 
236             if cpu_int > current_max_cpu:
237                 current_max_cpu = cpu_int
238 # Now separate the main overall csv file into per CPU csv files.
239     ipt.split_csv(current_max_cpu, cpu_mask)
240 
241 
242 def signal_handler(signal, frame):
243     print(' SIGINT: Forcing cleanup before exit.')
244     if interval:
245         ipt.disable_trace(trace_file)
246         ipt.clear_trace_file()
247         ipt.free_trace_buffer()
248         sys.exit(0)
249 
250 trace_file = "/sys/kernel/tracing/events/amd_cpu/enable"
251 signal.signal(signal.SIGINT, signal_handler)
252 
253 interval = ""
254 file_name = ""
255 cpu_list = ""
256 test_name = ""
257 memory = "10240"
258 graph_data_present = False;
259 
260 valid1 = False
261 valid2 = False
262 
263 cpu_mask = zeros((MAX_CPUS,), dtype=int)
264 
265 
266 try:
267     opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
268 except getopt.GetoptError:
269     ipt.print_help('amd_pstate')
270     sys.exit(2)
271 for opt, arg in opts:
272     if opt == '-h':
273         print()
274         sys.exit()
275     elif opt in ("-t", "--trace_file"):
276         valid1 = True
277         location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
278         file_name = os.path.join(location, arg)
279     elif opt in ("-i", "--interval"):
280         valid1 = True
281         interval = arg
282     elif opt in ("-c", "--cpu"):
283         cpu_list = arg
284     elif opt in ("-n", "--name"):
285         valid2 = True
286         test_name = arg
287     elif opt in ("-m", "--memory"):
288         memory = arg
289 
290 if not (valid1 and valid2):
291     ipt.print_help('amd_pstate')
292     sys.exit()
293 
294 if cpu_list:
295     for p in re.split("[,]", cpu_list):
296         if int(p) < MAX_CPUS :
297             cpu_mask[int(p)] = 1
298 else:
299     for i in range (0, MAX_CPUS):
300         cpu_mask[i] = 1
301 
302 if not os.path.exists('results'):
303     os.mkdir('results')
304     ipt.fix_ownership('results')
305 
306 os.chdir('results')
307 if os.path.exists(test_name):
308     print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
309     sys.exit()
310 os.mkdir(test_name)
311 ipt.fix_ownership(test_name)
312 os.chdir(test_name)
313 
314 cur_version = sys.version_info
315 print('python version (should be >= 2.7):')
316 print(cur_version)
317 
318 cleanup_data_files()
319 
320 if interval:
321     file_name = "/sys/kernel/tracing/trace"
322     ipt.clear_trace_file()
323     ipt.set_trace_buffer_size(memory)
324     ipt.enable_trace(trace_file)
325     time.sleep(int(interval))
326     ipt.disable_trace(trace_file)
327 
328 current_max_cpu = 0
329 
330 read_trace_data(file_name, cpu_mask)
331 
332 if interval:
333     ipt.clear_trace_file()
334     ipt.free_trace_buffer()
335 
336 if graph_data_present == False:
337     print('No valid data to plot')
338     sys.exit(2)
339 
340 for cpu_no in range(0, current_max_cpu + 1):
341     plot_per_cpu_freq(cpu_no)
342     plot_per_cpu_des_perf(cpu_no)
343     plot_per_cpu_load(cpu_no)
344 
345 plot_all_cpu_des_perf()
346 plot_all_cpu_frequency()
347 plot_all_cpu_load()
348 
349 for root, dirs, files in os.walk('.'):
350     for f in files:
351         ipt.fix_ownership(f)
352 
353 os.chdir('../../')

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php