|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
|
2 # Use of this source code is governed by a BSD-style license that can be |
|
3 # found in the LICENSE file. |
|
4 |
|
5 import re |
|
6 |
|
7 import android_commands |
|
8 import math |
|
9 |
|
10 # Valid values of result type. |
|
11 RESULT_TYPES = {'unimportant': 'RESULT ', |
|
12 'default': '*RESULT ', |
|
13 'informational': ''} |
|
14 |
|
15 |
|
16 def _EscapePerfResult(s): |
|
17 """Escapes |s| for use in a perf result.""" |
|
18 # Colons (:) and equal signs (=) are not allowed, and we chose an arbitrary |
|
19 # limit of 40 chars. |
|
20 return re.sub(':|=', '_', s[:40]) |
|
21 |
|
22 |
|
23 def PrintPerfResult(measurement, trace, values, units, result_type='default', |
|
24 print_to_stdout=True): |
|
25 """Prints numerical data to stdout in the format required by perf tests. |
|
26 |
|
27 The string args may be empty but they must not contain any colons (:) or |
|
28 equals signs (=). |
|
29 |
|
30 Args: |
|
31 measurement: A description of the quantity being measured, e.g. "vm_peak". |
|
32 trace: A description of the particular data point, e.g. "reference". |
|
33 values: A list of numeric measured values. |
|
34 units: A description of the units of measure, e.g. "bytes". |
|
35 result_type: A tri-state that accepts values of ['unimportant', 'default', |
|
36 'informational']. 'unimportant' prints RESULT, 'default' prints *RESULT |
|
37 and 'informational' prints nothing. |
|
38 print_to_stdout: If True, prints the output in stdout instead of returning |
|
39 the output to caller. |
|
40 |
|
41 Returns: |
|
42 String of the formated perf result. |
|
43 """ |
|
44 assert result_type in RESULT_TYPES, 'result type: %s is invalid' % result_type |
|
45 |
|
46 assert isinstance(values, list) |
|
47 assert len(values) |
|
48 assert '/' not in measurement |
|
49 avg = None |
|
50 sd = None |
|
51 if len(values) > 1: |
|
52 try: |
|
53 value = '[%s]' % ','.join([str(v) for v in values]) |
|
54 avg = sum([float(v) for v in values]) / len(values) |
|
55 sqdiffs = [(float(v) - avg) ** 2 for v in values] |
|
56 variance = sum(sqdiffs) / (len(values) - 1) |
|
57 sd = math.sqrt(variance) |
|
58 except ValueError: |
|
59 value = ", ".join(values) |
|
60 else: |
|
61 value = values[0] |
|
62 |
|
63 trace_name = _EscapePerfResult(trace) |
|
64 output = '%s%s: %s%s%s %s' % ( |
|
65 RESULT_TYPES[result_type], |
|
66 _EscapePerfResult(measurement), |
|
67 trace_name, |
|
68 # Do not show equal sign if the trace is empty. Usually it happens when |
|
69 # measurement is enough clear to describe the result. |
|
70 '= ' if trace_name else '', |
|
71 value, |
|
72 units) |
|
73 if avg: |
|
74 output += '\nAvg %s: %f%s' % (measurement, avg, units) |
|
75 if sd: |
|
76 output += '\nSd %s: %f%s' % (measurement, sd, units) |
|
77 if print_to_stdout: |
|
78 print output |
|
79 return output |
|
80 |
|
81 |
|
82 class PerfTestSetup(object): |
|
83 """Provides methods for setting up a device for perf testing.""" |
|
84 _DROP_CACHES = '/proc/sys/vm/drop_caches' |
|
85 _SCALING_GOVERNOR = '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' |
|
86 |
|
87 def __init__(self, adb): |
|
88 self._adb = adb |
|
89 num_cpus = self._adb.GetFileContents('/sys/devices/system/cpu/online', |
|
90 log_result=False) |
|
91 assert num_cpus, 'Unable to find /sys/devices/system/cpu/online' |
|
92 self._num_cpus = int(num_cpus[0].split('-')[-1]) |
|
93 self._original_scaling_governor = None |
|
94 |
|
95 def DropRamCaches(self): |
|
96 """Drops the filesystem ram caches for performance testing.""" |
|
97 if not self._adb.IsRootEnabled(): |
|
98 self._adb.EnableAdbRoot() |
|
99 self._adb.RunShellCommand('sync') |
|
100 self._adb.RunShellCommand('echo 3 > ' + PerfTestSetup._DROP_CACHES) |
|
101 |
|
102 def SetUp(self): |
|
103 """Sets up performance tests.""" |
|
104 if not self._original_scaling_governor: |
|
105 self._original_scaling_governor = self._adb.GetFileContents( |
|
106 PerfTestSetup._SCALING_GOVERNOR % 0, |
|
107 log_result=False)[0] |
|
108 self._SetScalingGovernorInternal('performance') |
|
109 self.DropRamCaches() |
|
110 |
|
111 def TearDown(self): |
|
112 """Tears down performance tests.""" |
|
113 if self._original_scaling_governor: |
|
114 self._SetScalingGovernorInternal(self._original_scaling_governor) |
|
115 self._original_scaling_governor = None |
|
116 |
|
117 def _SetScalingGovernorInternal(self, value): |
|
118 for cpu in range(self._num_cpus): |
|
119 self._adb.RunShellCommand( |
|
120 ('echo %s > ' + PerfTestSetup._SCALING_GOVERNOR) % (value, cpu)) |