Index: tools/telemetry/telemetry/internal/platform/power_monitor/sysfs_power_monitor.py |
diff --git a/tools/telemetry/telemetry/internal/platform/power_monitor/sysfs_power_monitor.py b/tools/telemetry/telemetry/internal/platform/power_monitor/sysfs_power_monitor.py |
deleted file mode 100644 |
index 85e5d30b681341c31ecaa69572280152cdf29109..0000000000000000000000000000000000000000 |
--- a/tools/telemetry/telemetry/internal/platform/power_monitor/sysfs_power_monitor.py |
+++ /dev/null |
@@ -1,230 +0,0 @@ |
-# Copyright 2014 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
- |
-import collections |
-import logging |
-import os |
-import re |
- |
-from telemetry.internal.platform import power_monitor |
-from telemetry import decorators |
- |
- |
-CPU_PATH = '/sys/devices/system/cpu/' |
- |
- |
-class SysfsPowerMonitor(power_monitor.PowerMonitor): |
- """PowerMonitor that relies on sysfs to monitor CPU statistics on several |
- different platforms. |
- """ |
- # TODO(rnephew): crbug.com/513453 |
- # Convert all platforms to use standalone power monitors. |
- def __init__(self, linux_based_platform_backend, standalone=False): |
- """Constructor. |
- |
- Args: |
- linux_based_platform_backend: A LinuxBasedPlatformBackend object. |
- standalone: If it is not wrapping another monitor, set to True. |
- |
- Attributes: |
- _cpus: A list of the CPUs on the target device. |
- _end_time: The time the test stopped monitoring power. |
- _final_cstate: The c-state residency times after the test. |
- _final_freq: The CPU frequency times after the test. |
- _initial_cstate: The c-state residency times before the test. |
- _initial_freq: The CPU frequency times before the test. |
- _platform: A LinuxBasedPlatformBackend object associated with the |
- target platform. |
- _start_time: The time the test started monitoring power. |
- """ |
- super(SysfsPowerMonitor, self).__init__() |
- self._cpus = None |
- self._final_cstate = None |
- self._final_freq = None |
- self._initial_cstate = None |
- self._initial_freq = None |
- self._platform = linux_based_platform_backend |
- self._standalone = standalone |
- |
- @decorators.Cache |
- def CanMonitorPower(self): |
- return bool(self._platform.RunCommand( |
- 'if [ -e %s ]; then echo true; fi' % CPU_PATH)) |
- |
- def StartMonitoringPower(self, browser): |
- del browser # unused |
- self._CheckStart() |
- if self.CanMonitorPower(): |
- self._cpus = filter( # pylint: disable=deprecated-lambda |
- lambda x: re.match(r'^cpu[0-9]+', x), |
- self._platform.RunCommand('ls %s' % CPU_PATH).split()) |
- self._initial_freq = self.GetCpuFreq() |
- self._initial_cstate = self.GetCpuState() |
- |
- def StopMonitoringPower(self): |
- self._CheckStop() |
- try: |
- out = {} |
- if SysfsPowerMonitor.CanMonitorPower(self): |
- self._final_freq = self.GetCpuFreq() |
- self._final_cstate = self.GetCpuState() |
- frequencies = SysfsPowerMonitor.ComputeCpuStats( |
- SysfsPowerMonitor.ParseFreqSample(self._initial_freq), |
- SysfsPowerMonitor.ParseFreqSample(self._final_freq)) |
- cstates = SysfsPowerMonitor.ComputeCpuStats( |
- self._platform.ParseCStateSample(self._initial_cstate), |
- self._platform.ParseCStateSample(self._final_cstate)) |
- for cpu in frequencies: |
- out[cpu] = {'frequency_percent': frequencies.get(cpu)} |
- out[cpu] = {'cstate_residency_percent': cstates.get(cpu)} |
- if self._standalone: |
- return self.CombineResults(out, {}) |
- return out |
- finally: |
- self._initial_cstate = None |
- self._initial_freq = None |
- |
- def GetCpuState(self): |
- """Retrieve CPU c-state residency times from the device. |
- |
- Returns: |
- Dictionary containing c-state residency times for each CPU. |
- """ |
- stats = {} |
- for cpu in self._cpus: |
- cpu_idle_path = os.path.join(CPU_PATH, cpu, 'cpuidle') |
- if not self._platform.PathExists(cpu_idle_path): |
- logging.warning( |
- 'Cannot read cpu c-state residency times for %s due to %s not exist' |
- % (cpu, cpu_idle_path)) |
- continue |
- cpu_state_path = os.path.join(cpu_idle_path, 'state*') |
- output = self._platform.RunCommand( |
- 'cat %s %s %s; date +%%s' % ( |
- os.path.join(cpu_state_path, 'name'), |
- os.path.join(cpu_state_path, 'time'), |
- os.path.join(cpu_state_path, 'latency'))) |
- stats[cpu] = re.sub('\n\n+', '\n', output) |
- return stats |
- |
- def GetCpuFreq(self): |
- """Retrieve CPU frequency times from the device. |
- |
- Returns: |
- Dictionary containing frequency times for each CPU. |
- """ |
- stats = {} |
- for cpu in self._cpus: |
- cpu_freq_path = os.path.join( |
- CPU_PATH, cpu, 'cpufreq/stats/time_in_state') |
- if not self._platform.PathExists(cpu_freq_path): |
- logging.warning( |
- 'Cannot read cpu frequency times for %s due to %s not existing' |
- % (cpu, cpu_freq_path)) |
- stats[cpu] = None |
- continue |
- try: |
- stats[cpu] = self._platform.GetFileContents(cpu_freq_path) |
- except Exception as e: |
- logging.warning( |
- 'Cannot read cpu frequency times in %s due to error: %s' % |
- (cpu_freq_path, e.message)) |
- stats[cpu] = None |
- return stats |
- |
- @staticmethod |
- def ParseFreqSample(sample): |
- """Parse a single frequency sample. |
- |
- Args: |
- sample: The single sample of frequency data to be parsed. |
- |
- Returns: |
- A dictionary associating a frequency with a time. |
- """ |
- sample_stats = {} |
- for cpu in sample: |
- frequencies = {} |
- if sample[cpu] is None: |
- sample_stats[cpu] = None |
- continue |
- for line in sample[cpu].splitlines(): |
- pair = line.split() |
- freq = int(pair[0]) * 10 ** 3 |
- timeunits = int(pair[1]) |
- if freq in frequencies: |
- frequencies[freq] += timeunits |
- else: |
- frequencies[freq] = timeunits |
- sample_stats[cpu] = frequencies |
- return sample_stats |
- |
- @staticmethod |
- def ComputeCpuStats(initial, final): |
- """Parse the CPU c-state and frequency values saved during monitoring. |
- |
- Args: |
- initial: The parsed dictionary of initial statistics to be converted |
- into percentages. |
- final: The parsed dictionary of final statistics to be converted |
- into percentages. |
- |
- Returns: |
- Dictionary containing percentages for each CPU as well as an average |
- across all CPUs. |
- """ |
- cpu_stats = {} |
- # Each core might have different states or frequencies, so keep track of |
- # the total time in a state or frequency and how many cores report a time. |
- cumulative_times = collections.defaultdict(lambda: (0, 0)) |
- for cpu in initial: |
- current_cpu = {} |
- total = 0 |
- if not initial[cpu] or not final[cpu]: |
- cpu_stats[cpu] = collections.defaultdict(int) |
- continue |
- for state in initial[cpu]: |
- current_cpu[state] = final[cpu][state] - initial[cpu][state] |
- total += current_cpu[state] |
- if total == 0: |
- # Somehow it's possible for initial and final to have the same sum, |
- # but a different distribution, making total == 0. crbug.com/426430 |
- cpu_stats[cpu] = collections.defaultdict(int) |
- continue |
- for state in current_cpu: |
- current_cpu[state] /= (float(total) / 100.0) |
- # Calculate the average c-state residency across all CPUs. |
- time, count = cumulative_times[state] |
- cumulative_times[state] = (time + current_cpu[state], count + 1) |
- cpu_stats[cpu] = current_cpu |
- average = {} |
- for state in cumulative_times: |
- time, count = cumulative_times[state] |
- average[state] = time / float(count) |
- cpu_stats['platform_info'] = average |
- return cpu_stats |
- |
- @staticmethod |
- def CombineResults(cpu_stats, power_stats): |
- """Add frequency and c-state residency data to the power data. |
- |
- Args: |
- cpu_stats: Dictionary containing CPU statistics. |
- power_stats: Dictionary containing power statistics. |
- |
- Returns: |
- Dictionary in the format returned by StopMonitoringPower. |
- """ |
- if not cpu_stats: |
- return power_stats |
- if 'component_utilization' not in power_stats: |
- power_stats['component_utilization'] = {} |
- if 'platform_info' in cpu_stats: |
- if 'platform_info' not in power_stats: |
- power_stats['platform_info'] = {} |
- power_stats['platform_info'].update(cpu_stats['platform_info']) |
- del cpu_stats['platform_info'] |
- for cpu in cpu_stats: |
- power_stats['component_utilization'][cpu] = cpu_stats[cpu] |
- return power_stats |