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

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/turbostat/added_perf_counters.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 #!/bin/env python3
  2 # SPDX-License-Identifier: GPL-2.0
  3 
  4 import subprocess
  5 from shutil import which
  6 from os import pread
  7 
  8 class PerfCounterInfo:
  9         def __init__(self, subsys, event):
 10                 self.subsys = subsys
 11                 self.event = event
 12 
 13         def get_perf_event_name(self):
 14                 return f'{self.subsys}/{self.event}/'
 15 
 16         def get_turbostat_perf_id(self, counter_scope, counter_type, column_name):
 17                 return f'perf/{self.subsys}/{self.event},{counter_scope},{counter_type},{column_name}'
 18 
 19 PERF_COUNTERS_CANDIDATES = [
 20         PerfCounterInfo('msr', 'mperf'),
 21         PerfCounterInfo('msr', 'aperf'),
 22         PerfCounterInfo('msr', 'tsc'),
 23         PerfCounterInfo('cstate_core', 'c1-residency'),
 24         PerfCounterInfo('cstate_core', 'c6-residency'),
 25         PerfCounterInfo('cstate_core', 'c7-residency'),
 26         PerfCounterInfo('cstate_pkg', 'c2-residency'),
 27         PerfCounterInfo('cstate_pkg', 'c3-residency'),
 28         PerfCounterInfo('cstate_pkg', 'c6-residency'),
 29         PerfCounterInfo('cstate_pkg', 'c7-residency'),
 30         PerfCounterInfo('cstate_pkg', 'c8-residency'),
 31         PerfCounterInfo('cstate_pkg', 'c9-residency'),
 32         PerfCounterInfo('cstate_pkg', 'c10-residency'),
 33 ]
 34 present_perf_counters = []
 35 
 36 def check_perf_access():
 37         perf = which('perf')
 38         if perf is None:
 39                 print('SKIP: Could not find perf binary, thus could not determine perf access.')
 40                 return False
 41 
 42         def has_perf_counter_access(counter_name):
 43                 proc_perf = subprocess.run([perf, 'stat', '-e', counter_name, '--timeout', '10'],
 44                                                          capture_output = True)
 45 
 46                 if proc_perf.returncode != 0:
 47                         print(f'SKIP: Could not read {counter_name} perf counter.')
 48                         return False
 49 
 50                 if b'<not supported>' in proc_perf.stderr:
 51                         print(f'SKIP: Could not read {counter_name} perf counter.')
 52                         return False
 53 
 54                 return True
 55 
 56         for counter in PERF_COUNTERS_CANDIDATES:
 57                 if has_perf_counter_access(counter.get_perf_event_name()):
 58                         present_perf_counters.append(counter)
 59 
 60         if len(present_perf_counters) == 0:
 61                 print('SKIP: Could not read any perf counter.')
 62                 return False
 63 
 64         if len(present_perf_counters) != len(PERF_COUNTERS_CANDIDATES):
 65                 print(f'WARN: Could not access all of the counters - some will be left untested')
 66 
 67         return True
 68 
 69 if not check_perf_access():
 70         exit(0)
 71 
 72 turbostat_counter_source_opts = ['']
 73 
 74 turbostat = which('turbostat')
 75 if turbostat is None:
 76         print('Could not find turbostat binary')
 77         exit(1)
 78 
 79 timeout = which('timeout')
 80 if timeout is None:
 81         print('Could not find timeout binary')
 82         exit(1)
 83 
 84 proc_turbostat = subprocess.run([turbostat, '--list'], capture_output = True)
 85 if proc_turbostat.returncode != 0:
 86         print(f'turbostat failed with {proc_turbostat.returncode}')
 87         exit(1)
 88 
 89 EXPECTED_COLUMNS_DEBUG_DEFAULT = [b'usec', b'Time_Of_Day_Seconds', b'APIC', b'X2APIC']
 90 
 91 expected_columns = [b'CPU']
 92 counters_argv = []
 93 for counter in present_perf_counters:
 94         if counter.subsys == 'cstate_core':
 95                 counter_scope = 'core'
 96         elif counter.subsys == 'cstate_pkg':
 97                 counter_scope = 'package'
 98         else:
 99                 counter_scope = 'cpu'
100 
101         counter_type = 'delta'
102         column_name = counter.event
103 
104         cparams = counter.get_turbostat_perf_id(
105                 counter_scope = counter_scope,
106                 counter_type = counter_type,
107                 column_name = column_name
108         )
109         expected_columns.append(column_name.encode())
110         counters_argv.extend(['--add', cparams])
111 
112 expected_columns_debug = EXPECTED_COLUMNS_DEBUG_DEFAULT + expected_columns
113 
114 def gen_user_friendly_cmdline(argv_):
115         argv = argv_[:]
116         ret = ''
117 
118         while len(argv) != 0:
119                 arg = argv.pop(0)
120                 arg_next = ''
121 
122                 if arg in ('-i', '--show', '--add'):
123                         arg_next = argv.pop(0) if len(argv) > 0 else ''
124 
125                 ret += f'{arg} {arg_next} \\\n\t'
126 
127         # Remove the last separator and return
128         return ret[:-4]
129 
130 #
131 # Run turbostat for some time and send SIGINT
132 #
133 timeout_argv = [timeout, '--preserve-status', '-s', 'SIGINT', '-k', '3', '0.2s']
134 turbostat_argv = [turbostat, '-i', '0.50', '--show', 'CPU'] + counters_argv
135 
136 def check_columns_or_fail(expected_columns: list, actual_columns: list):
137         if len(actual_columns) != len(expected_columns):
138                 print(f'turbostat column check failed\n{expected_columns=}\n{actual_columns=}')
139                 exit(1)
140 
141         failed = False
142         for expected_column in expected_columns:
143                 if expected_column not in actual_columns:
144                         print(f'turbostat column check failed: missing column {expected_column.decode()}')
145                         failed = True
146 
147         if failed:
148                 exit(1)
149 
150 cmdline = gen_user_friendly_cmdline(turbostat_argv)
151 print(f'Running turbostat with:\n\t{cmdline}\n... ', end = '', flush = True)
152 proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True)
153 if proc_turbostat.returncode != 0:
154         print(f'turbostat failed with {proc_turbostat.returncode}')
155         exit(1)
156 
157 actual_columns = proc_turbostat.stdout.split(b'\n')[0].split(b'\t')
158 check_columns_or_fail(expected_columns, actual_columns)
159 print('OK')
160 
161 #
162 # Same, but with --debug
163 #
164 # We explicitly specify '--show CPU' to make sure turbostat
165 # don't show a bunch of default counters instead.
166 #
167 turbostat_argv.append('--debug')
168 
169 cmdline = gen_user_friendly_cmdline(turbostat_argv)
170 print(f'Running turbostat (in debug mode) with:\n\t{cmdline}\n... ', end = '', flush = True)
171 proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True)
172 if proc_turbostat.returncode != 0:
173         print(f'turbostat failed with {proc_turbostat.returncode}')
174         exit(1)
175 
176 actual_columns = proc_turbostat.stdout.split(b'\n')[0].split(b'\t')
177 check_columns_or_fail(expected_columns_debug, actual_columns)
178 print('OK')

~ [ 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