Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor operations to fully work on AArch64. #191

Merged
merged 3 commits into from
May 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 96 additions & 56 deletions pyperf/_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT = 38

OS_LINUX = sys.platform.startswith('linux')
PLATFORM_X86 = platform.machine() in ('x86', 'x86_64', 'amd64')


def is_root():
Expand Down Expand Up @@ -119,21 +120,23 @@ def write(self, tune):
pass


class IntelPstateOperation(Operation):
@staticmethod
def available():
return use_intel_pstate()


class TurboBoostMSR(Operation):
"""
Get/Set Turbo Boost mode of Intel CPUs using /dev/cpu/N/msr.
Get/Set Turbo Boost mode of x86 CPUs using /dev/cpu/N/msr
"""

@staticmethod
def available():
return (
OS_LINUX and
not use_intel_pstate() and
platform.machine() in ('x86', 'x86_64', 'amd64')
)
return OS_LINUX and PLATFORM_X86 and not use_intel_pstate()

def __init__(self, system):
Operation.__init__(self, 'Turbo Boost (MSR)', system)
super().__init__('Turbo Boost (MSR)', system)
self.cpu_states = {}
self.have_device = True

Expand Down Expand Up @@ -266,18 +269,14 @@ def write(self, tune):
break


class TurboBoostIntelPstate(Operation):
class TurboBoostIntelPstate(IntelPstateOperation):
"""
Get/Set Turbo Boost mode of Intel CPUs by reading from/writing into
/sys/devices/system/cpu/intel_pstate/no_turbo of the intel_pstate driver.
"""

@staticmethod
def available():
return use_intel_pstate()

def __init__(self, system):
Operation.__init__(self, 'Turbo Boost (intel_pstate)', system)
super().__init__('Turbo Boost (intel_pstate)', system)
self.path = sysfs_path("devices/system/cpu/intel_pstate/no_turbo")
self.enabled = None

Expand Down Expand Up @@ -337,54 +336,92 @@ def write(self, tune):
self.log_action("Turbo Boost %s: %s" % (action, msg))


class CPUGovernorIntelPstate(Operation):
class CPUGovernor(Operation):
"""
Get/Set CPU scaling governor of the intel_pstate driver.
Get/Set CPU scaling governor
"""
BENCHMARK_GOVERNOR = 'performance'

@staticmethod
def available():
return use_intel_pstate()
return os.path.exists(
sysfs_path("devices/system/cpu/cpu0/cpufreq/scaling_governor")
)

def __init__(self, system):
Operation.__init__(self, 'CPU scaling governor (intel_pstate)',
system)
self.path = sysfs_path("devices/system/cpu/cpu0/cpufreq/scaling_governor")
self.governor = None

def read_governor(self):
governor = self.read_first_line(self.path)
if governor:
self.governor = governor
else:
self.error("Unable to read CPU scaling governor from %s" % self.path)
super().__init__('CPU scaling governor', system)
self.device_syspath = sysfs_path("devices/system/cpu")

def read_governor(self, cpu):
filename = os.path.join(self.device_syspath, 'cpu%s/cpufreq/scaling_governor' % cpu)
try:
with open(filename, "r") as fp:
return fp.readline().rstrip()
except OSError as exc:
self.check_permission_error(exc)
self.error("Unable to read CPU scaling governor from %s" % filename)
return None

def show(self):
self.read_governor()
if not self.governor:
cpus = {}
for cpu in range(self.system.logical_cpu_count):
governor = self.read_governor(cpu)
if governor is not None:
cpus[cpu] = governor

infos = format_cpu_infos(cpus)
if not infos:
return
self.log_state('; '.join(infos))

self.log_state(self.governor)
self.tuned_for_benchmarks = (self.governor == self.BENCHMARK_GOVERNOR)
self.tuned_for_benchmarks = all(
governor == self.BENCHMARK_GOVERNOR for governor in cpus.values()
)
if not self.tuned_for_benchmarks:
self.advice('Use CPU scaling governor %r'
% self.BENCHMARK_GOVERNOR)

def write(self, tune):
self.read_governor()
if not self.governor:
return
def write_governor(self, filename, new_governor):
with open(filename, "r") as fp:
governor = fp.readline().rstrip()

new_governor = 'performance' if tune else 'powersave'
if new_governor == self.governor:
return
if new_governor == governor:
return False

with open(filename, "w") as fp:
fp.write(new_governor)
return True

def write_cpu(self, cpu, tune):
governor = self.read_governor(cpu)
if not governor:
self.warning("Unable to read governor of CPU %s" % (cpu))
return False

new_governor = self.BENCHMARK_GOVERNOR if tune else "powersave"
filename = os.path.join(self.device_syspath, 'cpu%s/cpufreq/scaling_governor' % cpu)
try:
write_text(self.path, new_governor)
return self.write_governor(filename, new_governor)
except OSError as exc:
self.error("Failed to set the CPU scaling governor: %s" % exc)
else:
self.log_action("CPU scaling governor set to %s" % new_governor)
self.check_permission_error(exc)
self.error("Unable to write governor of CPU %s: %s"
% (cpu, exc))

def write(self, tune):
modified = []
for cpu in self.system.cpus:
if self.write_cpu(cpu, tune):
modified.append(cpu)
if self.permission_error:
break

if modified:
cpus = format_cpu_list(modified)
if tune:
action = "set to performance"
else:
action = "reset to powersave"
self.log_action("CPU scaling governor of CPUs %s %s" % (cpus, action))


class LinuxScheduler(Operation):
Expand All @@ -398,7 +435,7 @@ def available():
return OS_LINUX

def __init__(self, system):
Operation.__init__(self, 'Linux scheduler', system)
super().__init__('Linux scheduler', system)
self.ncpu = None
self.linux_version = None

Expand Down Expand Up @@ -473,7 +510,7 @@ def available(cls):
return os.path.exists(cls.path)

def __init__(self, system):
Operation.__init__(self, 'ASLR', system)
super().__init__('ASLR', system)

def show(self):
line = self.read_first_line(self.path)
Expand Down Expand Up @@ -519,7 +556,7 @@ def available():
return os.path.exists(sysfs_path("devices/system/cpu/cpu0/cpufreq"))

def __init__(self, system):
Operation.__init__(self, 'CPU Frequency', system)
super().__init__('CPU Frequency', system)
self.device_syspath = sysfs_path("devices/system/cpu")

def read_cpu(self, cpu):
Expand Down Expand Up @@ -617,7 +654,7 @@ def available(cls):
return os.path.exists(cls.irq_path)

def __init__(self, system):
Operation.__init__(self, 'IRQ affinity', system)
super().__init__('IRQ affinity', system)
self.irq_affinity_path = os.path.join(self.irq_path, "%s/smp_affinity")
self.default_affinity_path = os.path.join(self.irq_path, 'default_smp_affinity')

Expand Down Expand Up @@ -828,13 +865,10 @@ def write(self, tune):
self.write_irqs(cpus)


class CheckNOHZFullIntelPstate(Operation):
@staticmethod
def available():
return use_intel_pstate()
class CheckNOHZFullIntelPstate(IntelPstateOperation):

def __init__(self, system):
Operation.__init__(self, 'Check nohz_full', system)
super().__init__('Check nohz_full', system)

def show(self):
nohz_full = self.read_first_line(sysfs_path('devices/system/cpu/nohz_full'))
Expand Down Expand Up @@ -865,7 +899,7 @@ def available(cls):
return os.path.exists(cls.path)

def __init__(self, system):
Operation.__init__(self, 'Power supply', system)
super().__init__('Power supply', system)

def read_power_supply(self):
# Python implementation of the on_ac_power shell script
Expand Down Expand Up @@ -912,7 +946,7 @@ def available(cls):
return os.path.exists(cls.path)

def __init__(self, system):
Operation.__init__(self, 'Perf event', system)
super().__init__('Perf event', system)

def read_max_sample_rate(self):
line = self.read_first_line(self.path)
Expand Down Expand Up @@ -950,18 +984,24 @@ def write(self, tune):


OPERATIONS = [
# Generic operations
PerfEvent,
ASLR,
LinuxScheduler,
CPUFrequency,
IRQAffinity,
PowerSupply,
vstinner marked this conversation as resolved.
Show resolved Hide resolved

# Setting the CPU scaling governor resets no_turbo
# and so must be set before Turbo Boost
CPUGovernorIntelPstate,
CPUGovernor,

# Intel Pstate Operations
TurboBoostIntelPstate,
CheckNOHZFullIntelPstate,

# X86 Operations
TurboBoostMSR,
IRQAffinity,
PowerSupply,
]


Expand Down