Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 logging | 5 import logging |
| 6 | 6 |
| 7 from crash.loglinear.feature import Feature | 7 from crash.loglinear.feature import Feature |
| 8 from crash.loglinear.feature import FeatureValue | 8 from crash.loglinear.feature import FeatureValue |
| 9 from crash.loglinear.feature import LogLinearlyScaled | 9 from crash.loglinear.feature import LogLinearlyScaled |
| 10 import libs.math.logarithms as lmath | 10 import libs.math.logarithms as lmath |
| 11 | 11 |
| 12 # TODO(katesonia): Move this to the config saved in datastore. | |
| 13 _MAX_FRAME_INDEX = 7 | |
| 14 | |
| 15 | 12 |
| 16 class TopFrameIndexFeature(Feature): | 13 class TopFrameIndexFeature(Feature): |
| 17 """Returns the minimum frame index scaled between -inf and 0. | 14 """Returns the minimum frame index scaled between -inf and 0. |
| 18 | 15 |
| 19 That is, the normal-domain value is scaled linearly between 0 and 1, | 16 That is, the normal-domain value is scaled linearly between 0 and 1, |
| 20 but since we want to return a log-domain value we take the logarithm | 17 but since we want to return a log-domain value we take the logarithm |
| 21 of that (hence -inf to 0). This ensures that when a suspect has a | 18 of that (hence -inf to 0). This ensures that when a suspect has a |
| 22 linearly-scaled value of 0 (aka log-scaled value of -inf) we absolutely | 19 linearly-scaled value of 0 (aka log-scaled value of -inf) we absolutely |
| 23 refuse to blame that suspect. This heuristic behavior is intended. Before | 20 refuse to blame that suspect. This heuristic behavior is intended. Before |
| 24 changing it to be less aggressive about refusing to blame the suspect, | 21 changing it to be less aggressive about refusing to blame the suspect, |
| 25 we should delta test to be sure the new heuristic acts as indented. | 22 we should delta test to be sure the new heuristic acts as indented. |
| 26 | 23 |
| 27 When the actual minimum frame index is zero, we return the log-domain | 24 When the actual minimum frame index is zero, we return the log-domain |
| 28 value 0 (aka normal-domain value of 1). When the suspect has no frames or | 25 value 0 (aka normal-domain value of 1). When the suspect has no frames or |
| 29 the actual minimum frame index is greater than the ``max_frame_index``, | 26 the actual minimum frame index is greater than the ``max_frame_index``, |
| 30 we return the log-domain value -inf (aka normal-domain value of 0). In | 27 we return the log-domain value -inf (aka normal-domain value of 0). In |
| 31 between we scale the normal-domain values linearly, which means the | 28 between we scale the normal-domain values linearly, which means the |
| 32 log-domain values are scaled exponentially. | 29 log-domain values are scaled exponentially. |
| 33 """ | 30 """ |
| 34 def __init__(self, max_frame_index=None): | 31 def __init__(self, max_frame_index): |
|
chanli
2017/01/23 21:52:33
So no need for default any more?
Sharu Jiang
2017/01/23 23:02:17
Yes, the default value will be set in meta feature
| |
| 35 """ | 32 """ |
| 36 Args: | 33 Args: |
| 37 max_frame_index (int): An upper bound on the minimum frame index | 34 max_frame_index (int): An upper bound on the minimum frame index |
| 38 to consider. This argument is optional and defaults to | 35 to consider. |
| 39 ``_MAX_FRAME_INDEX``. | |
| 40 """ | 36 """ |
| 41 if max_frame_index is None: | |
| 42 max_frame_index = _MAX_FRAME_INDEX | |
| 43 self.max_frame_index = max_frame_index | 37 self.max_frame_index = max_frame_index |
| 44 | 38 |
| 45 @property | 39 @property |
| 46 def name(self): | 40 def name(self): |
| 47 return 'TopFrameIndex' | 41 return 'TopFrameIndex' |
| 48 | 42 |
| 49 def __call__(self, report): | 43 def __call__(self, report): |
| 50 """The minimum ``StackFrame.index`` across all files and stacks. | 44 """The minimum ``StackFrame.index`` across all files and stacks. |
| 51 | 45 |
| 52 Args: | 46 Args: |
| 53 report (CrashReport): the crash report being analyzed. | 47 report (CrashReportWithDependencies): the crash report being analyzed. |
| 54 | 48 |
| 55 Returns: | 49 Returns: |
| 56 A function from ``Suspect`` to the scaled minimum frame index, as a | 50 A function from ``Suspect`` to the scaled minimum frame index, as a |
| 57 log-domain ``float``. | 51 log-domain ``float``. |
| 58 """ | 52 """ |
| 59 def FeatureValueGivenReport(result): | 53 def FeatureValueGivenReport( |
| 60 if not result.file_to_stack_infos: | 54 suspect, touched_file_to_stack_infos): # pylint: disable=W0613 |
| 61 logging.warning('No StackInfo for any file: %s' % str(result)) | 55 """Computes ``FeatureValue`` for a suspect. |
| 62 return FeatureValue(self.name, lmath.LOG_ZERO, | |
| 63 "No StackInfo for any file", None) | |
| 64 | 56 |
| 65 top_frame_index = min(min(frame.index for frame, _ in stack_infos) | 57 Args: |
| 66 for stack_infos | 58 suspect (Suspect): The suspected changelog and some meta information |
| 67 in result.file_to_stack_infos.itervalues()) | 59 about it. |
| 60 touched_file_to_stack_infos(dict): Dict mapping ``FileChangeInfo`` to | |
| 61 a list of ``StackInfo``s representing all the frames that the suspect | |
| 62 touched. | |
| 63 | |
| 64 Returns: | |
| 65 The ``FeatureValue`` of this feature. | |
| 66 """ | |
| 67 if not touched_file_to_stack_infos: | |
| 68 return FeatureValue( | |
| 69 self.name, lmath.LOG_ZERO, | |
| 70 'No frame got touched by the suspect.', None) | |
| 71 | |
| 72 def TopFrameIndexForTouchedFile(stack_infos): | |
| 73 return min([stack_info.frame.index for stack_info in stack_infos]) | |
| 74 | |
| 75 top_frame_index = min([ | |
| 76 TopFrameIndexForTouchedFile(stack_infos) for _, stack_infos in | |
| 77 touched_file_to_stack_infos.iteritems()]) | |
| 78 | |
| 68 return FeatureValue( | 79 return FeatureValue( |
| 69 name = self.name, | 80 name = self.name, |
| 70 value = LogLinearlyScaled(float(top_frame_index), | 81 value = LogLinearlyScaled(float(top_frame_index), |
| 71 float(self.max_frame_index)), | 82 float(self.max_frame_index)), |
| 72 reason = ('Top frame is #%d' % top_frame_index), | 83 reason = ('Top frame is #%d' % top_frame_index), |
| 73 changed_files = None) | 84 changed_files = None) |
| 74 | 85 |
| 75 return FeatureValueGivenReport | 86 return FeatureValueGivenReport |
| OLD | NEW |