| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import numbers | 5 import numbers |
| 6 import math | 6 import math |
| 7 | 7 |
| 8 from telemetry import value as value_module | 8 from telemetry import value as value_module |
| 9 from telemetry.value import none_values | 9 from telemetry.value import none_values |
| 10 from telemetry.value import summarizable | 10 from telemetry.value import summarizable |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 class ListOfScalarValues(summarizable.SummarizableValue): | 66 class ListOfScalarValues(summarizable.SummarizableValue): |
| 67 """ ListOfScalarValues represents a list of numbers. | 67 """ ListOfScalarValues represents a list of numbers. |
| 68 | 68 |
| 69 By default, std is the standard deviation of all numbers in the list. Std can | 69 By default, std is the standard deviation of all numbers in the list. Std can |
| 70 also be specified in the constructor if the numbers are not from the same | 70 also be specified in the constructor if the numbers are not from the same |
| 71 population. | 71 population. |
| 72 """ | 72 """ |
| 73 def __init__(self, page, name, units, values, | 73 def __init__(self, page, name, units, values, |
| 74 important=True, description=None, | 74 important=True, description=None, |
| 75 tir_label=None, none_value_reason=None, | 75 tir_label=None, none_value_reason=None, |
| 76 std=None, same_page_merge_policy=value_module.CONCATENATE, | 76 std=None, improvement_direction=None, grouping_keys=None): |
| 77 improvement_direction=None, grouping_keys=None): | |
| 78 super(ListOfScalarValues, self).__init__(page, name, units, important, | 77 super(ListOfScalarValues, self).__init__(page, name, units, important, |
| 79 description, tir_label, | 78 description, tir_label, |
| 80 improvement_direction, | 79 improvement_direction, |
| 81 grouping_keys) | 80 grouping_keys) |
| 82 if values is not None: | 81 if values is not None: |
| 83 assert isinstance(values, list) | 82 assert isinstance(values, list) |
| 84 assert len(values) > 0 | 83 assert len(values) > 0 |
| 85 assert all(isinstance(v, numbers.Number) for v in values) | 84 assert all(isinstance(v, numbers.Number) for v in values) |
| 86 assert std is None or isinstance(std, numbers.Number) | 85 assert std is None or isinstance(std, numbers.Number) |
| 87 else: | 86 else: |
| 88 assert std is None | 87 assert std is None |
| 89 none_values.ValidateNoneValueReason(values, none_value_reason) | 88 none_values.ValidateNoneValueReason(values, none_value_reason) |
| 90 self.values = values | 89 self.values = values |
| 91 self.none_value_reason = none_value_reason | 90 self.none_value_reason = none_value_reason |
| 92 self.same_page_merge_policy = same_page_merge_policy | |
| 93 if values is not None and std is None: | 91 if values is not None and std is None: |
| 94 std = StandardDeviation(values) | 92 std = StandardDeviation(values) |
| 95 assert std is None or std >= 0, ( | 93 assert std is None or std >= 0, ( |
| 96 'standard deviation cannot be negative: %s' % std) | 94 'standard deviation cannot be negative: %s' % std) |
| 97 self._std = std | 95 self._std = std |
| 98 | 96 |
| 99 @property | 97 @property |
| 100 def std(self): | 98 def std(self): |
| 101 return self._std | 99 return self._std |
| 102 | 100 |
| 103 @property | 101 @property |
| 104 def variance(self): | 102 def variance(self): |
| 105 return self._std ** 2 | 103 return self._std ** 2 |
| 106 | 104 |
| 107 def __repr__(self): | 105 def __repr__(self): |
| 108 if self.page: | 106 if self.page: |
| 109 page_name = self.page.display_name | 107 page_name = self.page.display_name |
| 110 else: | 108 else: |
| 111 page_name = 'None' | 109 page_name = 'None' |
| 112 if self.same_page_merge_policy == value_module.CONCATENATE: | |
| 113 merge_policy = 'CONCATENATE' | |
| 114 else: | |
| 115 merge_policy = 'PICK_FIRST' | |
| 116 return ('ListOfScalarValues(%s, %s, %s, %s, ' | 110 return ('ListOfScalarValues(%s, %s, %s, %s, ' |
| 117 'important=%s, description=%s, tir_label=%s, std=%s, ' | 111 'important=%s, description=%s, tir_label=%s, std=%s, ' |
| 118 'same_page_merge_policy=%s, improvement_direction=%s, ' | 112 'improvement_direction=%s, grouping_keys=%s)') % ( |
| 119 'grouping_keys=%s)') % ( | |
| 120 page_name, | 113 page_name, |
| 121 self.name, | 114 self.name, |
| 122 self.units, | 115 self.units, |
| 123 repr(self.values), | 116 repr(self.values), |
| 124 self.important, | 117 self.important, |
| 125 self.description, | 118 self.description, |
| 126 self.tir_label, | 119 self.tir_label, |
| 127 self.std, | 120 self.std, |
| 128 merge_policy, | |
| 129 self.improvement_direction, | 121 self.improvement_direction, |
| 130 self.grouping_keys) | 122 self.grouping_keys) |
| 131 | 123 |
| 132 def GetBuildbotDataType(self, output_context): | 124 def GetBuildbotDataType(self, output_context): |
| 133 if self._IsImportantGivenOutputIntent(output_context): | 125 if self._IsImportantGivenOutputIntent(output_context): |
| 134 return 'default' | 126 return 'default' |
| 135 return 'unimportant' | 127 return 'unimportant' |
| 136 | 128 |
| 137 def GetBuildbotValue(self): | 129 def GetBuildbotValue(self): |
| 138 return self.values | 130 return self.values |
| 139 | 131 |
| 140 def GetRepresentativeNumber(self): | 132 def GetRepresentativeNumber(self): |
| 141 return _Mean(self.values) | 133 return _Mean(self.values) |
| 142 | 134 |
| 143 def GetRepresentativeString(self): | 135 def GetRepresentativeString(self): |
| 144 return repr(self.values) | 136 return repr(self.values) |
| 145 | 137 |
| 146 def IsMergableWith(self, that): | |
| 147 return (super(ListOfScalarValues, self).IsMergableWith(that) and | |
| 148 self.same_page_merge_policy == that.same_page_merge_policy) | |
| 149 | |
| 150 @staticmethod | 138 @staticmethod |
| 151 def GetJSONTypeName(): | 139 def GetJSONTypeName(): |
| 152 return 'list_of_scalar_values' | 140 return 'list_of_scalar_values' |
| 153 | 141 |
| 154 def AsDict(self): | 142 def AsDict(self): |
| 155 d = super(ListOfScalarValues, self).AsDict() | 143 d = super(ListOfScalarValues, self).AsDict() |
| 156 d['values'] = self.values | 144 d['values'] = self.values |
| 157 d['std'] = self.std | 145 d['std'] = self.std |
| 158 | 146 |
| 159 if self.none_value_reason is not None: | 147 if self.none_value_reason is not None: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 172 if 'none_value_reason' in value_dict: | 160 if 'none_value_reason' in value_dict: |
| 173 kwargs['none_value_reason'] = value_dict['none_value_reason'] | 161 kwargs['none_value_reason'] = value_dict['none_value_reason'] |
| 174 | 162 |
| 175 return ListOfScalarValues(**kwargs) | 163 return ListOfScalarValues(**kwargs) |
| 176 | 164 |
| 177 @classmethod | 165 @classmethod |
| 178 def MergeLikeValuesFromSamePage(cls, values): | 166 def MergeLikeValuesFromSamePage(cls, values): |
| 179 assert len(values) > 0 | 167 assert len(values) > 0 |
| 180 v0 = values[0] | 168 v0 = values[0] |
| 181 | 169 |
| 182 if v0.same_page_merge_policy == value_module.PICK_FIRST: | |
| 183 return ListOfScalarValues( | |
| 184 v0.page, v0.name, v0.units, | |
| 185 values[0].values, | |
| 186 important=v0.important, | |
| 187 same_page_merge_policy=v0.same_page_merge_policy, | |
| 188 none_value_reason=v0.none_value_reason, | |
| 189 improvement_direction=v0.improvement_direction, | |
| 190 grouping_keys=v0.grouping_keys) | |
| 191 | |
| 192 assert v0.same_page_merge_policy == value_module.CONCATENATE | |
| 193 return cls._MergeLikeValues(values, v0.page, v0.name, v0.tir_label, | 170 return cls._MergeLikeValues(values, v0.page, v0.name, v0.tir_label, |
| 194 v0.grouping_keys) | 171 v0.grouping_keys) |
| 195 | 172 |
| 196 @classmethod | 173 @classmethod |
| 197 def MergeLikeValuesFromDifferentPages(cls, values): | 174 def MergeLikeValuesFromDifferentPages(cls, values): |
| 198 assert len(values) > 0 | 175 assert len(values) > 0 |
| 199 v0 = values[0] | 176 v0 = values[0] |
| 200 return cls._MergeLikeValues(values, None, v0.name, v0.tir_label, | 177 return cls._MergeLikeValues(values, None, v0.name, v0.tir_label, |
| 201 v0.grouping_keys) | 178 v0.grouping_keys) |
| 202 | 179 |
| 203 @classmethod | 180 @classmethod |
| 204 def _MergeLikeValues(cls, values, page, name, tir_label, grouping_keys): | 181 def _MergeLikeValues(cls, values, page, name, tir_label, grouping_keys): |
| 205 v0 = values[0] | 182 v0 = values[0] |
| 206 merged_values = [] | 183 merged_values = [] |
| 207 list_of_samples = [] | 184 list_of_samples = [] |
| 208 none_value_reason = None | 185 none_value_reason = None |
| 209 pooled_std = None | 186 pooled_std = None |
| 210 for v in values: | 187 for v in values: |
| 211 if v.values is None: | 188 if v.values is None: |
| 212 merged_values = None | 189 merged_values = None |
| 213 none_value_reason = none_values.MERGE_FAILURE_REASON | 190 merged_none_values = [v for v in values if v.values is None] |
| 191 none_value_reason = (none_values.MERGE_FAILURE_REASON + |
| 192 ' None values: %s' % repr(merged_none_values)) |
| 214 break | 193 break |
| 215 merged_values.extend(v.values) | 194 merged_values.extend(v.values) |
| 216 list_of_samples.append(v.values) | 195 list_of_samples.append(v.values) |
| 217 if merged_values and page is None: | 196 if merged_values and page is None: |
| 218 # Pooled standard deviation is only used when merging values comming from | 197 # Pooled standard deviation is only used when merging values comming from |
| 219 # different pages. Otherwise, fall back to the default computation done | 198 # different pages. Otherwise, fall back to the default computation done |
| 220 # in the cosntructor of ListOfScalarValues. | 199 # in the cosntructor of ListOfScalarValues. |
| 221 pooled_std = PooledStandardDeviation( | 200 pooled_std = PooledStandardDeviation( |
| 222 list_of_samples, list_of_variances=[v.variance for v in values]) | 201 list_of_samples, list_of_variances=[v.variance for v in values]) |
| 223 return ListOfScalarValues( | 202 return ListOfScalarValues( |
| 224 page, name, v0.units, | 203 page, name, v0.units, |
| 225 merged_values, | 204 merged_values, |
| 226 important=v0.important, | 205 important=v0.important, |
| 227 description=v0.description, | 206 description=v0.description, |
| 228 tir_label=tir_label, | 207 tir_label=tir_label, |
| 229 same_page_merge_policy=v0.same_page_merge_policy, | |
| 230 std=pooled_std, | 208 std=pooled_std, |
| 231 none_value_reason=none_value_reason, | 209 none_value_reason=none_value_reason, |
| 232 improvement_direction=v0.improvement_direction, | 210 improvement_direction=v0.improvement_direction, |
| 233 grouping_keys=grouping_keys) | 211 grouping_keys=grouping_keys) |
| OLD | NEW |