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